Kernel Startup

BootLoader

GRUB



Version 2 (GRUB)

  • Stage 1boot.img is stored in the master boot record (MBR) or optionally in any of the volume boot records (VBRs), and addresses the next stage by an LBA48 address (thus, the 1024-cylinder limitation of GRUB legacy is avoided); at installation time it is configured to load the first sector of core.img.
  • Stage 1.5: core.img is by default written to the sectors between the MBR and the first partition, when these sectors are free and available. For legacy reasons, the first partition of a hard drive does not begin at sector 1 (counting begins with 0) but at sector 63, leaving 62 sectors of empty space not part of any partition or file system, and therefore not prone to any problems related with it. Once executed, core.img will load its configuration file and any other modules needed, particularly file system drivers; at installation time, it is generated from diskboot.img and configured to load the stage 2 by its file path.
  • Stage 2: files belonging to the stage 2 are all being held in the /boot/grub, which is a subdirectory of the /boot directory specified by the Filesystem Hierarchy Standard (FHS).



Once GRUB stage 2 has loaded, it presents a TUI-based operating system selection (kernel selection) menu, where the user can select which operating system to boot. GRUB can be configured to automatically load a specified kernel after a user-defined timeout; if the timeout is set to zero seconds, pressing and holding ⇧ Shift while the computer is booting makes it possible to access the boot menu.
Once boot options have been selected, GRUB loads the selected kernel into memory and passes control to the kernel. Alternatively, GRUB can pass control of the boot process to another boot loader, using chain loading. This is the method used to load operating systems such as Microsoft Windows, that do not support the Multiboot Specification or are not supported directly by GRUB.

https://en.wikipedia.org/wiki/GNU_GRUB



U-Boot


U-boot is a boot loader similar to lilo or grub, but is specifically designed for embedded devices. 



Stage 1 (Secondary Program Loader / SPL)

This preliminary piece of code is responsible for board initialization, loading the u-boot binary (“secondary program”) and handling the control flow over to the u-boot main program. The secondary program loader (SPL) and the u-boot binary reside in a special on-board flash memory region or on the first sectors of the uSD/eMMC card

Stage 2 (u-boot)

At the second stage of the boot process, the u-boot main program is executed.
The automatic boot process executes a special u-boot macro called bootcmd, which loads and executes the following procedures:
  • (opt.) a custom u-boot environment: uEnv.txt
  • (opt.) a precompiled u-boot macro: boot.scr
  • the kernel image, e.g. uImage
  • (opt.) the device tree binary, e. g. meson8b_odroidc.dtb
  • (opt.) the initial ramdisk, e. g. uInitrd

Stage 3 (Linux kernel)

The third stage is the loading of the Linux kernel. The kernel initializes the hardware, mounts the root filesystem (according to the root=...kernel parameter) and passes the control flow to /sbin/init.

https://github.com/umiddelb/armhf/wiki/Get-more-out-of-%22Das-U-Boot%22
https://github.com/u-boot/u-boot
http://lxr.linux.no/linux+v2.6.25.6/Documentation/i386/boot.txt
https://www.thegeekstuff.com/2011/02/linux-boot-process
https://manybutfinite.com/post/kernel-boot-process/

System Startup

Step 1(BIOS)


On an embedded platform, a bootstrap environment is used when the system is powered on, or reset. Examples include U-Boot, RedBoot, and MicroMonitor from Lucent. These programs reside in special region of flash memory on the target hardware and provide the means to download a Linux kernel image into flash memory and subsequently execute it. In addition to having the ability to store and boot a Linux image, these boot monitors perform some level of system test and hardware initialization. In an embedded target, these boot monitors commonly cover both the first- and second-stage boot loaders.


In a PC, booting Linux begins in the BIOS at address 0xFFFF0. The first step of the BIOS is the power-on self test (POST). The job of the POST is to perform a check of the hardware. The second step of the BIOS is local device enumeration and initialization.

Step 2(MBR Loading)


To boot an operating system, the BIOS runtime searches for devices that are both active and bootable. Commonly, Linux is booted from a hard disk, where the Master Boot Record (MBR) contains the primary boot loader. The MBR is a 512-byte sector, located in the first sector on the disk (sector 1 of cylinder 0, head 0). After the MBR is loaded into RAM, the BIOS yields control to it.

Step 3 (Stage 1 bootloader)


The primary boot loader that resides in the MBR is a 512-byte image containing both program code and a small partition table (see Figure 2). The first 446 bytes are the primary boot loader, which contains both executable code and error message text. The next sixty-four bytes are the partition table, which contains a record for each of four partitions (sixteen bytes each). The MBR ends with two bytes that are defined as the magic number (0xAA55). The magic number serves as a validation check of the MBR.


The job of the primary boot loader is to find and load the secondary boot loader (stage 2). It does this by looking through the partition table for an active partition. When it finds an active partition, it scans the remaining partitions in the table to ensure that they're all inactive. When this is verified, the active partition's boot record is read from the device into RAM and executed.

Step 4 (Stage 2 bootloader)


The secondary, or second-stage, boot loader could be more aptly called the kernel loader. The task at this stage is to load the Linux kernel and optional initial RAM disk.


The first- and second-stage boot loaders combined are called Linux Loader (LILO) or GRand Unified Bootloader (GRUB) in the x86 PC environment.


Instead of using raw sectors on the disk, as LILO does, GRUB can load a Linux kernel from an ext2 or ext3 file system. It does this by making the two-stage boot loader into a three-stage boot loader. Stage 1 (MBR) boots a stage 1.5 boot loader that understands the particular file system containing the Linux kernel image.


With the second-stage boot loader in memory, the file system is consulted, and the default kernel image and initrd image are loaded into memory. With the images ready, the stage 2 boot loader invokes the kernel image.

Step 5(Kernel)



With the kernel image in memory and control given from the stage 2 boot loader, the kernel
stage begins. The kernel image isn't so much an executable kernel, but a compressed kernel image.



At the head of this kernel image is a routine that does some minimal amount of hardware setup and then decompresses the kernel contained within the kernel image and places it into high memory.


If an initial RAM disk image is present, this routine moves it into memory and notes it for later use. The routine then calls the kernel and the kernel boot begins.


When the bzImage (for an i386 image) is invoked, you begin at ./arch/i386/boot/head.S in thestart assembly routine (see Figure 3 for the major flow). This routine does some basic hardware setup and invokes the startup_32 routine in ./arch/i386/boot/compressed/head.S.

 This routine sets up a basic environment (stack, etc.) and clears the Block Started by Symbol (BSS). The kernel is then decompressed through a call to a C function called decompress_kernel (located in ./ arch/i386/boot/compressed/misc.c). 

When the kernel is decompressed into memory, it is called. This is yet another startup_32 function, but this function is in ./arch/i386/kernel/head.S.


In the new startup_32 function (also called the swapper or process 0), the page tables are initialized and memory paging is enabled. The type of CPU is detected along with any optional floating-point unit (FPU) and stored away for later use. The start_kernel function is then invoked (init/main.c), which takes you to the non-architecture specific Linux kernel. This is, in essence, the main function for the Linux kernel.

Step 6


With the call to start_kernel, a long list of initialization functions are called to set up interrupts, perform further memory configuration, and load the initial RAM disk. In the end, a call is made tokernel_thread (in arch/i386/kernel/process.c) to start the init function, which is the first user- space process. Finally, the idle task is started and the scheduler can now take control (after the call to cpu_idle). With interrupts enabled, the pre-emptive scheduler periodically takes control to provide multitasking.


During the boot of the kernel, the initial-RAM disk (initrd) that was loaded into memory by the stage 2 boot loader is copied into RAM and mounted. This initrd serves as a temporary root file system in RAM and allows the kernel to fully boot without having to mount any physical disks. Since the necessary modules needed to interface with peripherals can be part of the initrd, the kernel can be very small, but still support a large number of possible hardware configurations. After the kernel is booted, the root file system is pivoted (via pivot_root) where the initrd root file system is unmounted and the real root file system is mounted.


The initrd function allows you to create a small Linux kernel with drivers compiled as loadable modules. These loadable modules give the kernel the means to access disks and the file systems on those disks, as well as drivers for other hardware assets. Because the root file system is a file system on a disk, the initrd function provides a means of bootstrapping to gain access to the disk and mount the real root file system. In an embedded target without a hard disk, the initrd can be the final root file system, or the final root file system can be mounted via the Network File System (NFS).

Step Last (Init)


After the kernel is booted and initialized, the kernel starts the first user-space application. This is the first program invoked that is compiled with the standard C library. Prior to this point in the process, no standard C applications have been executed.


In a desktop Linux system, the first application started is commonly /sbin/init. But it need
not be. 
In many cases, you can invoke a simple shell script that starts the necessary embedded applications.

OS(Android) StartUp Process

<hr>






  • first process start by kernel is the init process, which will look for a file called init.rc. The init process will parse the script and launches the system service processes. The init spawns the low level Linux processes called "daemons" e.g. android debug daemon, USB daemon etc. These daemons typically handle the low level hardware interfaces including radio interface.
  • zygote is one of the processes launched by the init process.
    This is the process which initializes the very first instance of Dalvik virtual machine and pre-loads all the common classes used by the application framework and the various apps. Then it starts listening on a socket interface for future requests to spawn off new vms for managing new app processes. On receiving a new request, it forks itself to create a new process which gets a pre-initialized vm instance. The zygote then forks to start a well managed process called system server. 
  • System Server starts all core platform services e.g activity manager service and hardware services in its own context. At this point the full stack is ready to launch the first app process - Home app which displays the home screen.

http://mutsughost1.github.io/2015/01/28/android-booting-process/ https://stackoverflow.com/questions/21612801/what-is-the-first-process-a-typical-linux-kernel-starts
https://www.ibm.com/developerworks/community/blogs/58e72888-6340-46ac-b488-d31aa4058e9c/entry/an_overview_of_linux_processes21?lang=en
https://community.nxp.com/docs/DOC-102546

https://stackoverflow.com/questions/21612801/what-is-the-first-process-a-typical-linux-kernel-starts

Android Application Launch

When a user clicks on an icon and a new application gets launched. 


The click event gets translated into startActivity(intent) call which gets routed to startActivity(intent) call in ActivityManagerServicethrough Binder IPC. The ActvityManagerService takes couple of actions - 

  • The first step is to collect information about the target of the intent object. This is done by using resolveIntent() method on PackageManager object. 
  • The target information is saved back into the intent object to avoid re-doing this step.
  • Next important step is to check if user has enough privileges to invoke the target component of the intent. 
  • If user has enough permissions, ActivityManagerService checks if the target activity requires to be launched in a new task. 
  • Now, it's the time to check if the ProcessRecord already exists for the process.
If the ProcessRecord is null, the ActivityManager has to create a new process to instantiate the target component.

Process Creation - 

ActivityManagerService creates a new process by invoking startProcessLocked() method which sends arguments to Zygote process over the socket connection. Zygote forks itself and calls ZygoteInit.main() which then instantiates ActivityThread object and finally returns pid of newly created process. 
ActivityThread then starts the message loop by calling Looper.prepareLoop() and Looper.loop() subsequently.
Application Binding - 

The next step is to attach the process to the specific application. This is done by calling bindApplication on the thread object. This method sends BIND_APPLICATION message to the message queue. This message is retrieved by the handler object which then invokes handleMessage() method to trigger the message specific action - handleBindApplication(). This method invokes makeApplication() method which loads app specific classes into memory.

Activity Launch - 

After the previous step, the system contains the process responsible for the application with application classes loaded in process's private memory. The call sequence to launch an activity is common between a newly created process and an existing process. The actual process of launching starts in realStartActivity() method which calls sheduleLaunchActivity() on the application thread object. This method sends LAUNCH_ACTIVITY message to the message queue. The message is handled by handleLaunchActivity() method as shown below.






  • Every Android app has its own Dalvik VM instance, so that Two applications that don't trust one another shouldn't be able to view each other's memory, even if they use native code or reflectiona and If a process leaks memory and crashes, it harms only itself.
  • The Dalvik heap is preloaded with classes and data by zygote. When zygote forks to start an android application, the new application gets a copy-on-write mapping of this heap. This helps with memory reduction as well as application startup time

http://multi-core-dump.blogspot.com/2010/04/android-application-launch-part-2.html
https://github.com/aosp-mirror/platform_frameworks_base/tree/master/core/java/android/os https://www.youtube.com/watch?v=aFGbv9Ih9qQ

https://medium.com/@martinomburajr/android-internals-1-how-android-starts-your-main-activity-8fcf80e65222

Kernel Driver Module


load a kernel module automatically at boot time


Append the driver module name in the module file (For Debian Linux or Ubuntu Linux use the file /etc/modules file instead of /etc/modules.conf, modern Linux kernels - /etc/modules-load.d/kvm.conf) and restart the device.

lsmod
modinfo {module_name}


Custom Kernel Building

https://www.yoctoproject.org/docs/1.6.1/yocto-project-qs/yocto-project-qs.html#building-image http://www.ti.com/lit/an/spraah2a/spraah2a.pdf

https://github.com/umiddelb/armhf/wiki/How-To-compile-a-custom-Linux-kernel-for-your-ARM-device
https://elinux.org/Kernel_Size_Tuning_Guide
https://wiki.yoctoproject.org/wiki/Minimal_Image
https://elinux.org/Kernel_Size_Tuning_Guide_Config_Option_Impact

Comments

Popular posts from this blog

Thread & Locks

Opengl-es Buffer