2026-04-30 11:48:50 +07:00
2026-04-30 11:48:50 +07:00

Module 3 - Operating System Booting

Prerequisite

  • Using VMware Player, with nested virtualization enabled.
  • Install Linux Ubuntu 22.04 with at least 4GB memory and 4 vCPU.

Learning Outcomes

  • Understand the Linux operating system booting process.
  • Understand the basic concepts of the Linux kernel and creating a root filesystem (initramfs).
  • Be able to compile the Linux kernel and create a root filesystem using BusyBox.
  • Be able to emulate an operating system using QEMU.
  • Be able to create a bootable ISO disk and run emulation using the ISO.

Table of Contents

Introduction

Imagine you are about to start a car. When you turn the key or press the start button, the engine starts, the electronic systems activate, and within seconds, the car is ready to use. But have you ever wondered what actually happens before the car is ready to drive?

The same thing happens when you turn on a computer or laptop. When you press the power button, the system does not immediately become "ready to use." There is a long process happening behind the scenes, and this is called the booting process.

Definition of Booting

Booting is the process that occurs from the moment a computer is powered on until the operating system is fully active and ready to use. This is a crucial initial stage in the life of an operating system because without a successful booting process, no applications can run.

General Booting Stages

The booting process can be divided into several main stages:

  1. Power-On Self Test (POST)
    Once the power button is pressed, the computer's firmware (such as BIOS or UEFI) will perform a POST. This is an initial check to ensure that key components like RAM, processor, and storage devices are functioning properly. If there is an issue, this process will display an error message or emit a beep sound.

  2. Searching for Boot Device & Executing Bootloader
    After POST is complete, the firmware will search for a boot device, which is the storage medium containing the operating system, based on a configured order (e.g., hard disk, USB, or CD). Within the boot device, the firmware will execute a small program called the bootloader, such as GRUB (on Linux) or bootmgr (on Windows). The bootloader is responsible for selecting and loading the operating system kernel into memory.

  3. Loading Kernel
    The kernel is the core of the operating system. It is responsible for managing communication between hardware and software, memory, processes, file systems, and more. Once loaded, the kernel will begin initializing all the system's essential components.

  4. Running Init
    After the kernel completes initialization, control of the system is handed over to the first process: init. This process then starts various other processes, such as network services, login shells, and desktop environments. Init can be a traditional system like SysVinit or a more modern system like systemd.

Types of Booting

There are two commonly known types of booting processes:

  • Cold Boot (Hard Boot)
    This is the booting process from a completely powered-off state. For example, when you turn on a laptop that is completely off, the process is called a cold boot.

  • Warm Boot (Soft Boot)
    This is the rebooting process of a system that is already running. This can be done, for example, by pressing the restart button or using the reboot command. Warm booting is often performed after a system update or when there is a minor issue that requires a restart.

Importance of the Booting Process and the Role of the Kernel

Without a proper booting process, the operating system cannot be run. No matter how advanced or complete the hardware is, without the booting process, a computer is just a pile of components that cannot do anything. The booting process is the gateway that opens the way for all operating system functions, from user login, running applications, to managing networks and external devices.

Each stage in the booting process has an important responsibility:

  • Firmware ensures that the hardware is ready.
  • Bootloader determines which operating system to run.
  • Kernel initializes all the essential elements of the system.
  • Init (the first process) runs the system's basic services.

Failure at any of these stages can cause the system to fail to boot, be unable to enter the operating system, or even crash. Therefore, understanding how the booting process works is very important, especially when developing operating systems or troubleshooting.

One of the most vital parts of this process is the kernel. The kernel acts as a bridge between hardware and software, managing communication between the processor, memory, input/output devices, and running programs. In Linux-based systems, this kernel is called the Linux Kernel.

Due to its central role, the booting process heavily depends on whether the kernel can be loaded and run properly. Therefore, in the next chapter, you will learn how to prepare the Linux kernel as the foundational element of a simple operating system that you will build and emulate yourself.

Linux Kernel

Definition of Linux Kernel

The Linux Kernel is the core of the Linux operating system. It manages the interaction between hardware and software and handles critical tasks such as memory management, processes, file systems, and input/output devices. The kernel is the first component to run after the bootloader loads it into memory.

One of the advantages of the Linux kernel is its open-source and modular nature. Anyone can view, modify, and recompile the kernel according to their needs. This makes it ideal for learning, experimentation, and developing customized operating systems, as you will do in this module.

In practice, we do not need to write a kernel from scratch. We simply take the official Linux kernel source code, then compile it into a binary file bzImage that can be executed by the bootloader and emulated by QEMU. The kernel compilation process requires several system dependencies and initial configurations to determine the features to include in the compiled kernel.

Preparing the Linux Kernel

At this stage, we will prepare the Linux kernel to be used for building a minimal operating system using QEMU.

QEMU is an open-source emulator that allows us to run operating systems in a virtual environment. With QEMU, we can test the kernel we have built without installing it directly on hardware. Further explanation about QEMU will be discussed in a separate section.

The steps to be performed include updating and installing supporting software, downloading the kernel source code, configuring the kernel as needed, and compiling the kernel to produce the bzImage file.

  1. Update and Install Supporting Software

    Before starting, ensure the system is updated and all necessary software for this process is installed. We will use several tools such as qemu, build-essential, bison, flex, and others.

    sudo apt -y update
    sudo apt -y install qemu-system build-essential bison flex libelf-dev libssl-dev bc grub-common grub-pc libncurses-dev libssl-dev mtools grub-pc-bin xorriso tmux
    
  2. Prepare the Directory

    Create a directory for this project and navigate to it. All kernel building and configuration processes will be performed within this directory.

    mkdir -p osboot
    cd osboot
    
  3. Download and Extract the Linux Kernel

    The next step is to download the Linux kernel source code version 6.1.1. After downloading, we will extract it into the linux-6.1.1 directory.

    wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.1.tar.xz
    tar -xvf linux-6.1.1.tar.xz
    cd linux-6.1.1
    
  4. Configure the Kernel

    The Linux kernel needs to be configured before being compiled. We will start by using a minimal configuration with make tinyconfig. After that, we can further customize the configuration using make menuconfig to enable features required by the operating system we are building. Some important settings to enable include support for virtualization, file systems, device drivers, and networking.

    64-Bit Kernel
    General Setup > Configure standard kernel features > Enable support for printk
    General Setup > Configure standard kernel features > Enable futex support
    General Setup > Initial RAM filesystem and RAM disk (initramfs/initrd) support
    General Setup > Control Group Support
    Enable the block layer > Legacy autoloading support
    Enable the block layer > Partition type > Advanced Partition Selection
    Device Drivers > Character devices > Enable TTY
    Device Drivers > Character devices > Virtio console
    Device Drivers > Character devices > /dev/mem virtual device support
    Device Drivers > Network device support > Virtio Network Driver
    Device Drivers > Serial Ata / Paralel ATA
    Device Drivers > Block Devices > Virtio block driver
    Device Drivers > Block Devices > loopback device support
    Device Drivers > Block Devices > RAM block device support
    Device Drivers > Virtio drivers
    Device Drivers > Virtualization Drivers
    Device Drivers > Generic  Driver Options > Maintain a devtmpfs at filesystems
    Device Drivers > Generic Driver Options > Automount devtmpfs at /dev
    Executable file formats > Kernel Support for ELF binaries
    Executable file formats > Kernel Support scripts starting with #!
    File Systems > FUSE support
    File Systems > The extended 3 filesystem
    File Systems > The extended 4 filesystem
    File Systems > Second extended fs support
    File Systems > Virtio Filesystem
    File Systems > Kernel automounter support
    File Systems > Pseudo File Systems > /proc file system support
    File Systems > Pseudo File Systems > sysctl support
    File Systems > Pseudo File Systems > sysfs file system support
    Networking Support > Networking options > Unix domain sockets
    Networking Support > Networking options > TCP/IP Networking
    

or you can use this script

make tinyconfig

./scripts/config --enable CONFIG_64BIT --enable CONFIG_PRINTK --enable CONFIG_FUTEX \
--enable CONFIG_BLK_DEV_INITRD --enable CONFIG_CGROUPS --enable CONFIG_TTY \
--enable CONFIG_VIRTIO_CONSOLE --enable CONFIG_DEVMEM --enable CONFIG_VIRTIO_NET \
--enable CONFIG_ATA --enable CONFIG_VIRTIO_BLK --enable CONFIG_BLK_DEV_LOOP \
--enable CONFIG_BLK_DEV_RAM --enable CONFIG_VIRTIO --enable CONFIG_VIRTUALIZATION \
--enable CONFIG_DEVTMPFS --enable CONFIG_DEVTMPFS_MOUNT --enable CONFIG_BINFMT_ELF \
--enable CONFIG_BINFMT_SCRIPT --enable CONFIG_FUSE_FS --enable CONFIG_EXT4_FS \
--enable CONFIG_VIRTIO_FS --enable CONFIG_PROC_FS --enable CONFIG_SYSFS \
--enable CONFIG_UNIX --enable CONFIG_INET

make olddefconfig

This configuration ensures that the resulting kernel can work well in a virtual environment and supports the basic operations required.

make tinyconfig
make menuconfig

After completing the configuration, you can save the .config file and proceed to the next step.

  1. Compile the Kernel

    With the configuration ready, we can now start the kernel compilation process. This process will produce the bzImage file, which is the kernel file ready for booting.

    make -j$(nproc)
    

    The command above compiles the kernel using all available CPU cores on the system.

  2. Generate the bzImage File

    After the compilation is complete, we will obtain the bzImage file in the arch/x86/boot/ directory. Move this file to the osboot directory in preparation for the next step, which is creating the root filesystem and emulating it using QEMU.

    cp arch/x86/boot/bzImage ..
    

Creating a Root Filesystem

Definition of Root Filesystem

Imagine an operating system as a house. The root filesystem is the foundation and basic framework of that house. All rooms (directories like /bin, /etc, /dev, etc.) are built on top of this rootfs, and all activities of the inhabitants (applications and services) depend on it for the house to function properly. Without rootfs, the house is like a structure without an entrance, tools, or rules.

What is a Root Filesystem?

  • The Root Filesystem is the file structure used by the operating system to store essential files required to run the system, such as configurations, hardware, and basic applications.
  • It is the first filesystem loaded after the booting process begins and serves as the central storage for all critical files needed by the system.

Components in a Root Filesystem

The root filesystem typically contains several important directories, including:

  • /bin Stores basic applications and programs used to run the system.
  • /etc Stores system and application configuration files.
  • /lib Contains system libraries required by programs to run.
  • /dev Stores device files needed to access hardware.
  • /home Directory for storing user data.

Initial RAM Filesystem (initramfs)

Before the main root filesystem can be mounted, the system requires a temporary filesystem called initramfs to start the operating system. Initramfs is a lightweight filesystem image loaded into memory during the initial booting phase.

Functions of Initramfs:

  • Provides basic tools and scripts to prepare the system.
  • Configures hardware and checks storage devices.
  • Supplies the kernel with the information needed to mount the main root filesystem.

BusyBox

To simplify tasks within initramfs, BusyBox is used as a collection of lightweight yet comprehensive tools. BusyBox provides various system utilities used to configure hardware, manipulate the filesystem, and perform other critical tasks during the booting process.

Functions of BusyBox:

  • Replaces many standard Linux commands in the operating system with lighter and simpler versions.
  • Functions in resource-constrained environments (such as embedded systems or the early booting stage).
  • Provides utilities like ls, cp, mv, mount, and many others, which are used by initramfs to perform various tasks.

Installing BusyBox

BusyBox can be installed using the following command:

sudo apt install -y busybox-static

You can check if BusyBox is installed with the command:

whereis busybox

Typically, BusyBox will be located in the /usr/bin/busybox directory.

Single User vs Multi User

The Linux operating system can run in two main modes based on user needs and system complexity: Single User and Multi User. Both use the root filesystem as the system's foundation but have different approaches, structures, and booting processes.

The Single User mode is suitable for system maintenance or debugging as it only allows one user (usually root) to access the system. Meanwhile, the Multi User mode is designed to allow multiple users to log in and work simultaneously, with access rights, accounts, and system services management.

Comparison: Single User vs Multi User

  1. From a Functional Perspective

    Aspect Single User Multi User
    Purpose Used for maintenance, debugging, or minimal systems. Used for daily use, servers, or systems with multiple users.
    User Access Only one user (usually root) can log in. Multiple users can log in simultaneously with different access rights.
    Interaction No interaction between users, focused on basic system tasks. Supports interaction between users and parallel processes.
    Security Minimal security settings as only root has access. Requires authentication systems, user management, and access rights for each user.
    Use Case Practical for recovery, boot testing, or very lightweight embedded systems. Common in desktop systems, servers, or work environments involving multiple users.
  2. From a System Creation Perspective

    Single User

    • Root Filesystem Structure:
      • Minimal: /bin, /dev, /proc, /sys, and the init file.
      • No user directories (/home, /etc/passwd, etc.).
    • init File:
      • Simple. Usually contains:
        #!/bin/sh
        echo "Init started"
        exec /bin/sh
        
      • After mounting, directly enters the shell as root without a login process.
    • User Management: Not required, as only root runs the shell.
    • Booting Process: Fast and simple, no login daemon or access rights management.

    Multi User

    • Root Filesystem Structure:
      • More complete: Includes /etc/passwd, /etc/group, /etc/shadow, /home/user1, etc.
      • Uses BusyBox for login, adduser, getty, and other system management tools.
    • init File:
      • More complex, as it must run the login process via getty:
        #!/bin/sh
        mount -t proc none /proc
        mount -t sysfs none /sys
        mount -t devtmpfs none /dev
        /bin/hostname multiuser
        setsid /bin/getty -n -l /bin/login 115200 tty1 &
        exec /bin/sh
        
      • Login process active on tty1, and can be added for tty2, tty3, etc.
    • User Management:
      • Users and groups must be created using adduser or manually editing /etc/passwd.
      • Passwords can be encrypted or left blank depending on BusyBox configuration.
    • Booting Process: The system runs a login prompt on multiple terminals (multi-console). After logging in, each user gets their own shell according to their access rights.
  3. Summary of Differences

    Aspect Single User Multi User
    Main Purpose Maintenance / minimal system System ready for use by multiple users
    Access Root only Multiple users with login
    Filesystem Complexity Simple Complete with user configuration
    init File Direct shell Login process via getty
    Additional Directories No need for /etc/passwd, /home, etc. Must include directories and user configuration files
    User Management None Requires authentication system
    Use Case Example Rescue mode, embedded systems Server, multi-user workstation

Conclusion

The main difference between single user and multi user lies not only in the number of users who can log in but also in the level of system complexity. The single user mode offers simplicity and speed, ideal for emergencies or lightweight embedded systems. Meanwhile, the multi user mode requires additional configuration but provides greater flexibility and scalability, suitable for production systems.

Single User

After preparing the kernel and root filesystem, we will proceed to create a simpler filesystem for the initial booting stage, known as Single User Mode. In Single User mode, the prepared root filesystem will run with only one user who has full control over the system. This mode is useful in the early stages of booting or for simpler systems, such as embedded systems, where only one user is needed to configure or manage the system. Below is a further explanation of how the root filesystem works in single user mode, along with steps to create this root filesystem.

Concept of Root Filesystem in Single User Mode

  1. Role of the init Program

    • After the Linux kernel starts the booting process, the first step is to run the init program. This init program is the first program executed by the kernel with Process ID (PID) 1.
    • init is responsible for setting up the environment needed by the system and starting other processes in the correct order.
    • The root filesystem initially loaded by the kernel will include the init program, which is usually located in the root directory (/).
  2. Using Initramfs in Single User Mode

    • To simplify the booting process, the root filesystem can be loaded using initramfs. Initramfs is a temporary filesystem loaded into memory and serves to prepare the system before the main root filesystem is mounted.
    • In this case, initramfs is used to configure the system and provide minimal tools, such as BusyBox, to run the init program in single user mode.
  3. Why Use BusyBox

    • In more complex operating systems, the root filesystem is usually stored on permanent storage such as a hard drive or SSD. However, during the initial booting process or on resource-constrained systems, we use BusyBox.
    • BusyBox is a collection of Unix/Linux utilities packaged into a single executable file. It enables a lighter system by providing various essential commands like ls, cp, mount, and sh, which are used to configure and manage the filesystem.

Steps to Create a Root Filesystem for Single User Mode

The steps to create a root filesystem using initramfs and BusyBox to provide a minimal yet functional system environment are as follows:

  1. Enter Superuser Mode

    To make changes to the system, we will work in superuser (root) mode. Use the following command to enter the shell as root:

    sudo bash
    
  2. Create a Directory for Initramfs

    Next, create a myramdisk directory and several subdirectories for the filesystem:

    mkdir -p myramdisk/{bin,dev,proc,sys}
    

    The directory structure will look like this:

    myramdisk/
        ├── bin/
        ├── dev/
        ├── proc/
        └── sys/
    
  3. Copy Device Files to the dev Directory

    The /dev directory in Linux contains important device files like null, tty, zero, and console. We will copy them from the host system into the dev directory in myramdisk.

    cp -a /dev/null myramdisk/dev
    cp -a /dev/tty* myramdisk/dev
    cp -a /dev/zero myramdisk/dev
    cp -a /dev/console myramdisk/dev
    
  4. Copy BusyBox to the bin Directory

    Next, copy the BusyBox file into the bin directory created inside myramdisk. Then, install all utilities provided by BusyBox:

    cp /usr/bin/busybox myramdisk/bin
    cd myramdisk/bin
    ./busybox --install .
    

    This command will add various Unix/Linux commands like ls, cp, mv, mount, and many others to the bin directory.

  5. Create the init File

    Inside the myramdisk directory, create an init file that will be executed first during booting. Populate this file with instructions to mount the filesystem and start an interactive shell.

    #!/bin/sh
    /bin/mount -t proc none /proc
    /bin/mount -t sysfs none /sys
    exec /bin/sh
    

    This file will mount proc and sysfs, enabling the system to communicate with the kernel. After that, it will start the /bin/sh shell for user interaction.

  6. Grant Execution Permission to the init File

    To make the init file executable, grant it execution permission using the command:

    chmod +x init
    
  7. Compress and Create the initramfs File

    After preparing all the necessary files, the next step is to package them using the cpio command and compress them with gzip to create the initramfs image.

    find . | cpio -oHnewc | gzip > ../myramdisk.gz
    

    This command will produce the myramdisk.gz file, which contains the minimal filesystem for the initial booting stage.

With the above steps, we have successfully created a root filesystem in single user mode using BusyBox and initramfs.

Multi User

After successfully running the system in single user mode, the next step is to build the system in multi user mode using initramfs. In this mode, more than one user can log in and use the system simultaneously, making it suitable for general use that requires account and access management.

To support multi user, we will construct a more complete root filesystem. We use BusyBox as the provider of basic Linux utilities and initramfs as the root filesystem loaded into memory during booting. Unlike single user mode, which only provides a direct shell for root, this mode requires a login process on the terminal, necessitating files like /etc/passwd, /etc/group, and services like getty.

Steps to Create a Root Filesystem for Multi User Mode

  1. Enter Privileged Mode (Superuser)

    To make changes to the system, we will work in superuser (root) mode using the command:

    sudo bash
    
  2. Create a Directory for Initramfs

    Create a directory named myramdisk and several subdirectories required by the root filesystem.

    mkdir -p myramdisk/{bin,dev,proc,sys,etc,root,home/user1}
    
  3. Copy Device Files to the dev Directory

    The /dev directory contains important devices like null, tty, zero, and console. We will copy these device files from the host system into the dev directory in myramdisk.

    cp -a /dev/null myramdisk/dev
    cp -a /dev/tty* myramdisk/dev
    cp -a /dev/zero myramdisk/dev
    cp -a /dev/console myramdisk/dev
    
  4. Copy BusyBox to the bin Directory

    Copy the BusyBox file into the bin directory and run the BusyBox utility installation:

    cp /usr/bin/busybox myramdisk/bin
    cd myramdisk/bin
    ./busybox --install .
    
  5. Create Root Password

    Use the openssl command to create an encrypted root password:

    openssl passwd -1 myrootpassword
    

    Copy the output of the above command, as it will be used to create the user and password database.

  6. Create the passwd File in the etc Directory

    Create a passwd file in the etc directory to store information about the root account and the user we will create (e.g., user1):

    root:<<generatedrootpassword>>:0:0:root:/root:/bin/sh
    user1:<<generateduserpassword>>:1001:100:user1:/home/user1:/bin/sh
    
  7. Create the group File in the etc Directory

    Create a group file in the etc directory containing group settings for the newly created user:

    root:x:0:
    bin:x:1:root
    sys:x:2:root
    tty:x:5:root,user1
    disk:x:6:root
    wheel:x:10:root,user1
    users:x:100:user1
    
  8. Create the init File

    Return to the myramdisk directory and create an init file that will be called by the bootloader during system booting. Populate the init file with instructions to mount the filesystem and run the login process:

    #!/bin/sh
    /bin/mount -t proc none /proc
    /bin/mount -t sysfs none /sys
    
    while true
    do
            /bin/getty -L tty1 115200 vt100
            sleep 1
    done
    

    This file will mount proc and sysfs, enabling communication between user space and the kernel. Then, the getty command will wait for login input from users via the console.

  9. Grant Execution Permission to the init File

    To make the init file executable, grant it execution permission:

    chmod +x init
    
  10. Compress and Create the initramfs File

    After preparing all the necessary files, we will package them using the **cpio** utility and then compress them with **gzip** to create the **initramfs** image.
    
    ```bash
    find . | cpio -oHnewc | gzip > ../myramdisk.gz
    ```
    
    This command will produce the **myramdisk.gz** file, which contains the minimal filesystem for booting.
    

With the above steps, we have successfully created a root filesystem with multi-user capabilities using initramfs and BusyBox. This system allows multiple users to log in, with one main user (root) and one additional user (user1). When the system boots, users can log in using the credentials we have defined.

Emulation with QEMU

Understanding QEMU

QEMU (Quick Emulator) is a program used to run operating systems or applications in a virtual environment (similar to another computer) without requiring different physical hardware. With QEMU, you can run different operating systems, such as Linux on Windows, or try entirely different systems, like ARM or RISC-V, on an x86-based machine (a regular computer).

Imagine you want to try a different system, for example, testing Windows 10 on a Mac. Instead of installing Windows directly on the Mac's hard drive (which can be time-consuming and risky), you can use QEMU to "emulate" a Windows machine inside the Mac, allowing you to test Windows 10 without changing anything on the original computer.

QEMU works by emulating (mimicking) components in a computer such as the CPU (processor), memory, and hardware. This allows you to run operating systems or applications that would normally only work on specific hardware, without needing the corresponding physical machine.

Difference Between QEMU and Virtual Machines (VM)

QEMU and Virtual Machines (VM) are often used for the same purpose, which is running different operating systems, but they differ in how they work.

  1. Virtual Machine (VM)

    • What is a VM? A VM is a virtual machine that runs on top of the main operating system. With a VM, you create a virtual machine that functions like a separate physical computer. You can run an operating system (e.g., Linux) on top of another operating system (e.g., Windows) using programs like VirtualBox or VMware.
    • How a VM Works: A virtual machine uses virtualization to divide the physical computer's resources (like CPU, RAM) into multiple virtual machines. So, even though all virtual machines share the same physical computer, they work as if they have their own separate computer.
  2. QEMU

    • What is QEMU? QEMU is a flexible emulator. QEMU can perform full emulation of a computer, meaning it can mimic hardware (like CPUs and other devices) from another machine. This allows you to run operating systems designed for different hardware (e.g., ARM, MIPS) on top of a different machine (e.g., x86).
    • How QEMU Works: QEMU not only supports virtualization but also emulation. This means QEMU can "mimic" hardware entirely, allowing you to run various types of operating systems without requiring the corresponding physical machine.
  3. Comparison Between QEMU and VM

    Aspect QEMU VM
    Technology Type Emulation (mimics hardware) Virtualization (shares physical resources)
    Main Function Runs operating systems from different architectures Runs multiple operating systems on one physical machine
    Use Case Example Running operating systems for different architectures (e.g., ARM on x86) Running multiple operating systems on one machine (e.g., Windows and Linux on one computer)

Steps for Emulation with QEMU

After creating the bzImage (kernel) and myramdisk.gz (initramfs) files, you can run the operating system you built using QEMU. Here are the steps to follow:

  1. Navigate to the osboot Directory

    First, go to the directory where you saved the build files:

    cd osboot
    

    This directory should contain the following files:

    • bzImage → the compiled kernel
    • myramdisk.gz → the root filesystem you created
  2. Run the Emulation with QEMU

    Use the following command to run QEMU with specific configurations:

    qemu-system-x86_64 \
    -smp 2 \
    -m 256 \
    -display curses \
    -vga std \
    -kernel bzImage \
    -initrd myramdisk.gz
    

    Explanation of Options:

    Option Function
    -smp 2 Provides 2 vCPUs (virtual CPUs) for the emulated system
    -m 256 Allocates 256 MB of memory
    -display curses Displays output in text mode (can be used in a regular terminal)
    -vga std Sets standard VGA display (80x25), sufficient for text display
    -kernel bzImage Specifies the kernel to use for booting
    -initrd myramdisk.gz Specifies the root filesystem (initramfs) to load

After running the above command, QEMU will start the booting process. If there are no errors, you will enter the BusyBox shell (if using an init script that launches a shell) or see a login process if using a multi-user configuration.

Testing Inside the Shell

Once the system successfully boots through QEMU, you will see a shell or login prompt depending on whether you are using single user or multi-user mode.

Single User

You will directly enter the sh shell provided by BusyBox. This means the system only provides direct access to the terminal without a login process.

Example display:

/ #

Here, you can try some basic Linux commands like:

ls
cat /proc/cpuinfo
echo "Hello from QEMU!"

The goal is to ensure that:

  • The file system is successfully loaded
  • BusyBox is functioning correctly
  • The system responds to input

Multi User

In this mode, you will see a login prompt. The system will ask you to log in using the username and password you configured earlier (e.g., in the /etc/passwd and /etc/shadow files).

Example display:

Welcome to Mini Linux
myos login: user1
Password:

After successfully logging in, you will enter the shell and can perform tests such as:

whoami
ls /home

Things to test:

  • The login process works correctly
  • User permissions are appropriate (cannot access root directories without permission)
  • You can navigate directories and execute basic commands

Restarting the Boot Process

If you want to restart the boot process of the system you emulated with QEMU, you need to stop the QEMU process first, then run it again as before.

  1. Stop the QEMU Process

    Use the following command to stop the QEMU process:

    pkill -f qemu
    

    This command will find processes containing the word "qemu" and terminate them. Ensure you are not running any other important processes with the same name.

  2. Run the System Again Using QEMU

    Repeat the same QEMU command as before:

    qemu-system-x86_64 \
      -smp 2 \
      -m 256 \
      -display curses \
      -vga std \
      -kernel bzImage \
      -initrd myramdisk.gz
    

This will reboot the system from the beginning with the same settings, allowing you to test again whether the system runs stably and as expected.

Creating a Bootable ISO Disk

A bootable ISO disk is a .iso file that contains a complete file system structure of an operating system and can be used for booting. This file can be run through emulators like QEMU, burned to a CD/DVD, or written to a USB drive to run the system directly (live system).

Creating an ISO is useful for:

  • Distributing a custom operating system
  • Quick testing and deployment to other machines
  • Building a custom minimal Linux live system

To make the ISO bootable, we need a bootloader, which is the initial program executed when the computer starts. Here, we will use GRUB (GRand Unified Bootloader) as the bootloader and combine it with the kernel (bzImage) and root filesystem (myramdisk.gz) into a single ISO using the grub-mkrescue tool.

Steps:

  1. Navigate to the osboot directory:

    cd osboot
    
  2. Create the ISO directory structure:

    mkdir -p mylinuxiso/boot/grub
    
  3. Copy the kernel and root filesystem files:

    cp bzImage mylinuxiso/boot
    cp myramdisk.gz mylinuxiso/boot
    
  4. Create the GRUB configuration file: Create a grub.cfg file in mylinuxiso/boot/grub with the following content:

    set timeout=5
    set default=0
    
    menuentry "MyLinux" {
      linux /boot/bzImage
      initrd /boot/myramdisk.gz
    }
    

    This file creates a GRUB menu displaying a boot option named "MyLinux" and directs the system to use the provided kernel and initrd.

  5. Generate the bootable ISO file: Run the following command from the osboot directory:

    grub-mkrescue -o mylinux.iso mylinuxiso
    

Emulating ISO File Execution

After successfully creating the bootable ISO file, the next step is to test the ISO using an emulator. Here, we will use QEMU to run the system we built, simulating booting from a virtual CD-ROM.

This emulation allows us to:

  • Verify that the bootable ISO system works correctly
  • Run the BusyBox shell from the ISO
  • Check the integration of the kernel and initramfs

Steps for Emulation:

  1. Navigate to the osboot directory:

    cd osboot
    
  2. Run the system with QEMU using the ISO file:

    qemu-system-x86_64 \
      -smp 2 \
      -m 256 \
      -display curses \
      -vga std \
      -cdrom mylinux.iso
    

    Explanation of parameters:

    • -smp 2 → uses 2 virtual CPUs
    • -m 256 → allocates 256 MB of RAM
    • -display curses → displays output in the terminal (text mode)
    • -vga std → standard VGA for 80x25 resolution display
    • -cdrom mylinux.iso → specifies the ISO file to boot

Results

  • The screen will display the booting process
  • A GRUB menu will appear with the option: MyLinux
  • After selecting, the system will load the kernel and initrd, then enter the BusyBox shell

Testing in BusyBox Shell

Once inside the shell, try the following commands to test the system environment:

ls -la
ls
whoami
ps

These commands will:

  • Display the directory contents (ls)
  • Show the active user (whoami)
  • List running processes (ps)

Restarting the Emulation

If you want to rerun the emulation:

  1. Stop QEMU with:

    pkill -f qemu
    
  2. Run the qemu-system-x86_64 command again as shown above.

Description
No description provided
Readme 38 KiB