You are not logged in.

#1 2025-07-01 14:06:56

ktauchathuranga
Member
Registered: 2025-05-25
Posts: 8

trying to build an minimal UEFI os but failing in VGA output

hi,
i am prettty new to this,
i just wanna create simple minimal UEFI linux os with busybox, so i can boot it to my pendrive and launch in my laptop,
but i am unable to get the output to the VGA.
i can get the nomrmal os output to the console, but in vga, i cant get the output to show.
i am using an Dell laptop if it relevant.
i will attach ss's and the my build script as well.
help would be much appreciated. smile


Screenshot


#!/bin/bash

# Exit immediately if a command exits with a non-zero status.
set -e

# --- Configuration ---
OS_NAME="PrivilegeOS"
KERNEL_VER="6.15.3"
BUSYBOX_VER="1.36.1"

# Source directories (assumed to be in the same folder as the script)
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
KERNEL_SRC_DIR="${SCRIPT_DIR}/linux-${KERNEL_VER}"
BUSYBOX_SRC_DIR="${SCRIPT_DIR}/busybox-${BUSYBOX_VER}"

# Build directory
BUILD_DIR="${SCRIPT_DIR}/build"
INITRAMFS_DIR="${BUILD_DIR}/initramfs"
USB_MNT_DIR="${BUILD_DIR}/usbmnt" # Mount point for USB flashing
DISK_IMG="${BUILD_DIR}/${OS_NAME}.img"

# This variable will be set later if we use a loop device
LOOP_DEV=""

# --- Helper Functions ---
log() {
    echo -e "\n\e[1;32m[INFO] ==> $1\e[0m"
}

error() {
    echo -e "\n\e[1;31m[ERROR] ==> $1\e[0m"
    exit 1
}

warn() {
    echo -e "\n\e[1;33m[WARNING] ==> $1\e[0m"
}

cleanup() {
    log "Cleaning up..."
    # Unmount USB mount point if it exists
    if mountpoint -q "${USB_MNT_DIR}"; then
        sudo umount "${USB_MNT_DIR}"
    fi
    # Detach loop device if it was used
    if [ -n "$LOOP_DEV" ] && losetup -a | grep -q "${LOOP_DEV}"; then
        sudo umount "${BUILD_DIR}/mnt" || true
        sudo losetup -d "${LOOP_DEV}" || true
    fi
}

trap cleanup EXIT

usage() {
    echo "Usage: $0 [action] [device]"
    echo "Actions:"
    echo "  run           Builds the disk image and runs it in QEMU. (Default)"
    echo "  build         Builds the disk image and exits."
    echo "  usb <device>  Builds and flashes the OS to a USB device (e.g., /dev/sdc)."
    echo "                !!! THIS IS DESTRUCTIVE AND WILL ERASE THE DEVICE !!!"
    exit 1
}


# --- Main Build Steps ---

check_dependencies() {
    log "Checking for dependencies..."
    # Added wipefs for cleaner partitioning
    local deps=("gcc" "make" "bc" "ncursesw6-config" "qemu-system-x86_64" "parted" "mkfs.vfat" "losetup" "wipefs")
    for dep in "${deps[@]}"; do
        if ! command -v "$dep" &> /dev/null; then
            error "Dependency '$dep' not found. Please install it."
        fi
    done
    if [ ! -f /usr/share/ovmf/x64/OVMF.fd ]; then
        error "OVMF firmware not found at /usr/share/ovmf/x64/OVMF.fd. Please install the 'ovmf' package. The path might also be 'OVMF_CODE.fd' on some systems."
    fi
    log "All dependencies are satisfied."
}

setup_workspace() {
    log "Setting up the build workspace..."
    if [ ! -d "$KERNEL_SRC_DIR" ]; then
        error "Kernel source directory not found: $KERNEL_SRC_DIR"
    fi
    if [ ! -d "$BUSYBOX_SRC_DIR" ]; then
        error "BusyBox source directory not found: $BUSYBOX_SRC_DIR"
    fi

    rm -rf "$BUILD_DIR"
    mkdir -p "$BUILD_DIR"
    mkdir -p "${INITRAMFS_DIR}"/{bin,sbin,etc,proc,sys,dev,usr/bin,usr/sbin}
    log "Workspace created at ${BUILD_DIR}"
}

build_busybox() {
    log "Building BusyBox..."
    cd "$BUSYBOX_SRC_DIR"
    
    make distclean
    make defconfig
    
    # Statically link BusyBox to avoid library dependencies
    sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config
    # This can sometimes cause build issues, disabling if not needed.
    sed -i 's/^CONFIG_TC=y/# CONFIG_TC is not set/' .config
    
    make -j$(nproc)
    make CONFIG_PREFIX="${INITRAMFS_DIR}" install
    
    cd "$SCRIPT_DIR"
    log "BusyBox build complete."
}

create_initramfs_content() {
    log "Creating initramfs content..."
    
    sudo mknod -m 622 "${INITRAMFS_DIR}/dev/console" c 5 1
    sudo mknod -m 666 "${INITRAMFS_DIR}/dev/null" c 1 3
    sudo mknod -m 666 "${INITRAMFS_DIR}/dev/zero" c 1 5

    cat <<EOF > "${INITRAMFS_DIR}/init"
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev
exec /sbin/init
EOF
    chmod +x "${INITRAMFS_DIR}/init"

    cat <<EOF > "${INITRAMFS_DIR}/etc/inittab"
::sysinit:/etc/init.d/rcS
tty1::askfirst:-/bin/sh
ttyS0::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
EOF

    mkdir -p "${INITRAMFS_DIR}/etc/init.d"
    cat <<EOF > "${INITRAMFS_DIR}/etc/init.d/rcS"
#!/bin/sh
echo ""
echo "  ____       _ _ _         _   ___  ____  "
echo " |  _ \ _ __(_) | |  _ __ (_) / _ \/ ___| "
echo " | |_) | '__| | | | | '_ \| |/ / | \___ \ "
echo " |  __/| |  | | | |_| |_) | / /| |___) |"
echo " |_|   |_|  |_|_|\___/ .__/|_\/  \____/ "
echo "                     |_|                "
echo ""
echo "Welcome to ${OS_NAME}! Type 'poweroff' or 'reboot' to exit."
echo ""
hostname -F /etc/hostname
EOF
    chmod +x "${INITRAMFS_DIR}/etc/init.d/rcS"

    echo "${OS_NAME}" > "${INITRAMFS_DIR}/etc/hostname"
    
    log "initramfs content created."
}

# --- FIXED build_kernel FUNCTION ---
build_kernel() {
    log "Building the Linux Kernel..."
    cd "$KERNEL_SRC_DIR"
    
    make mrproper
    make defconfig
    
    # --- QEMU Specific Drivers (Keep them for testing) ---
    ./scripts/config --enable CONFIG_VIRTIO_PCI
    ./scripts/config --enable CONFIG_VIRTIO_BLK
    ./scripts/config --enable CONFIG_VIRTIO_CONSOLE
    ./scripts/config --enable CONFIG_DRM_VIRTIO_GPU
    
    # --- Core UEFI/Boot Requirements (Correct) ---
    ./scripts/config --enable CONFIG_EFI_STUB
    ./scripts/config --enable CONFIG_EFI
    ./scripts/config --enable CONFIG_FB_EFI
    ./scripts/config --enable CONFIG_DEVTMPFS
    ./scripts/config --enable CONFIG_DEVTMPFS_MOUNT
    ./scripts/config --enable CONFIG_FRAMEBUFFER_CONSOLE
    ./scripts/config --enable CONFIG_LOGO
    ./scripts/config --enable CONFIG_LOGO_LINUX_CLUT224
    
    # --- Core Console/Serial (Correct) ---
    ./scripts/config --enable CONFIG_SERIAL_8250
    ./scripts/config --enable CONFIG_SERIAL_8250_CONSOLE

    # --- Generic Drivers for Real Hardware (Good start) ---
    ./scripts/config --enable CONFIG_SATA_AHCI # SATA disks
    ./scripts/config --enable CONFIG_USB_XHCI_HCD # USB 3.0
    ./scripts/config --enable CONFIG_USB_EHCI_HCD # USB 2.0
    ./scripts/config --enable CONFIG_USB_OHCI_HCD # USB 1.1
    ./scripts/config --enable CONFIG_USB_HID # Keyboards, Mice
    ./scripts/config --enable CONFIG_HID_GENERIC
    ./scripts/config --enable CONFIG_E1000E # Common Intel NIC
    ./scripts/config --enable CONFIG_SND_HDA_INTEL # Common Intel HD Audio

    # ====================================================================
    # --- Drivers for Real Physical GPUs (FIXED) ---
    # ====================================================================
    log "Enabling drivers for physical GPUs..."

    # Enable the main DRM (Direct Rendering Manager) subsystem
    ./scripts/config --enable CONFIG_DRM
    ./scripts/config --enable CONFIG_DRM_KMS_HELPER

    # Enable Intel i915 Driver (Most common for Dell laptops)
    ./scripts/config --enable CONFIG_DRM_I915
    # The i915 driver may need firmware (see explanation below)
    ./scripts/config --enable CONFIG_DRM_I915_CAPTURE_ERROR

    # --- FIX: Force probe i915 devices even if firmware is missing ---
    ./scripts/config --enable CONFIG_DRM_I915_FORCE_PROBE
    ./scripts/config --set-str CONFIG_DRM_I915_FORCE_PROBE "\"*\""

    # Ensure firmware loader is built-in (might help if we have firmware)
    ./scripts/config --enable CONFIG_FW_LOADER
    ./scripts/config --enable CONFIG_FW_LOADER_BUILTIN

    # (Optional but Recommended) Enable AMD GPU Driver for wider compatibility
    ./scripts/config --enable CONFIG_DRM_AMD
    ./scripts/config --enable CONFIG_DRM_AMDGPU
    
    # --- Initramfs config (Correct) ---
    ./scripts/config --enable CONFIG_INITRAMFS_SOURCE
    ./scripts/config --set-str CONFIG_INITRAMFS_SOURCE "${INITRAMFS_DIR}"
    
    # --- Command line (Correct) ---
    ./scripts/config --enable CONFIG_CMDLINE_BOOL
    # Using a more verbose command line for debugging on real hardware
    ./scripts/config --set-str CONFIG_CMDLINE "console=tty1 console=ttyS0,115200 loglevel=7"

    make olddefconfig
    make -j$(nproc) bzImage
    
    cd "$SCRIPT_DIR"
    log "Kernel build complete. Ready at ${KERNEL_SRC_DIR}/arch/x86/boot/bzImage"
}

install_to_uefi_target() {
    local TARGET_DEV="$1"
    local TARGET_IS_BLOCKDEV=false
    
    if [ -b "${TARGET_DEV}" ]; then
        TARGET_IS_BLOCKDEV=true
    fi
    
    if [ "$TARGET_IS_BLOCKDEV" = true ]; then
        log "Preparing to flash to block device ${TARGET_DEV}"
        warn "THIS WILL COMPLETELY ERASE ALL DATA ON ${TARGET_DEV}."
        
        echo -e "\n\e[1;33mDevice information:\e[0m"
        lsblk -o NAME,SIZE,MODEL "${TARGET_DEV}"
        
        read -p $'\n\e[1;31mARE YOU ABSOLUTELY SURE? Type YES to continue: \e[0m' CONFIRMATION
        if [ "${CONFIRMATION}" != "YES" ]; then
            error "Aborted by user."
        fi
        
        log "User confirmed. Wiping and partitioning ${TARGET_DEV}..."
        sudo umount "${TARGET_DEV}"* || true
        sudo wipefs -a "${TARGET_DEV}"
        
    else
        log "Creating UEFI disk image file..."
        dd if=/dev/zero of="${TARGET_DEV}" bs=1M count=256
    fi
    
    sudo parted -s "${TARGET_DEV}" mklabel gpt
    sudo parted -s "${TARGET_DEV}" mkpart ESP fat32 1MiB 100%
    sudo parted -s "${TARGET_DEV}" set 1 esp on
    
    if [ "$TARGET_IS_BLOCKDEV" = true ]; then
        log "Waiting for kernel to recognize new partition..."
        sleep 3
        sudo partprobe "${TARGET_DEV}"
        sleep 1
    fi
    
    local PARTITION
    if [ "$TARGET_IS_BLOCKDEV" = true ]; then
        # This logic handles both standard devices (sda -> sda1)
        # and NVMe devices (nvme0n1 -> nvme0n1p1).
        if [[ "${TARGET_DEV}" == *nvme* ]]; then
            PARTITION="${TARGET_DEV}p1"
        else
            PARTITION="${TARGET_DEV}1"
        fi
    else
        # This is the logic for file-based images
        LOOP_DEV=$(sudo losetup -f --show -P "${TARGET_DEV}")
        if [ -z "$LOOP_DEV" ]; then
            error "Failed to set up loopback device."
        fi
        PARTITION="${LOOP_DEV}p1"
    fi
    
    if [ ! -b "$PARTITION" ]; then
        error "Could not find partition device at '${PARTITION}'. The kernel may not have detected it."
    fi

    log "Formatting partition ${PARTITION} as FAT32..."
    sudo mkfs.vfat -F 32 "${PARTITION}"
    
    log "Mounting and copying EFI bootloader..."
    local MNT_POINT
    if [ "$TARGET_IS_BLOCKDEV" = true ]; then
        MNT_POINT="${USB_MNT_DIR}"
    else
        MNT_POINT="${BUILD_DIR}/mnt"
    fi
    
    mkdir -p "${MNT_POINT}"
    sudo mount "${PARTITION}" "${MNT_POINT}"
    sudo mkdir -p "${MNT_POINT}/EFI/BOOT"
    
    sudo cp "${KERNEL_SRC_DIR}/arch/x86/boot/bzImage" "${MNT_POINT}/EFI/BOOT/BOOTX64.EFI"
    
    log "Unmounting target..."
    sudo umount "${MNT_POINT}"
    
    if [ "$TARGET_IS_BLOCKDEV" = false ]; then
        sudo losetup -d "${LOOP_DEV}"
    else
        sync
    fi
    
    log "UEFI target ${TARGET_DEV} is ready."
}

run_qemu() {
    log "Starting QEMU..."
    qemu-system-x86_64 \
        -machine q35,accel=kvm \
        -cpu host \
        -m 2G \
        -smp 2 \
        -bios /usr/share/ovmf/x64/OVMF.4m.fd \
        -drive file="${DISK_IMG}",format=raw,if=virtio \
        -device intel-hda -device hda-output \
        -nic user,model=e1000e \
        -device usb-ehci -device usb-tablet \
        -serial stdio \
        -no-reboot
}

# --- Main Execution Flow ---
main() {
    ACTION="${1:-run}" # Default to 'run' if no action is specified

    case "$ACTION" in
        run)
          #  check_dependencies
          #  setup_workspace
          #  build_busybox
          #  create_initramfs_content
          #  build_kernel
            install_to_uefi_target "${DISK_IMG}"
            run_qemu
            ;;
        build)
            setup_workspace
            build_busybox
            create_initramfs_content
            build_kernel
            install_to_uefi_target "${DISK_IMG}"
            log "Build complete. Image is at ${DISK_IMG}"
            ;;
        usb)
            TARGET_USB_DEV="$2"
            if [ -z "$TARGET_USB_DEV" ]; then
                error "No target device specified for 'usb' action."
                usage
            fi
            if [ ! -b "$TARGET_USB_DEV" ]; then
                error "Target '${TARGET_USB_DEV}' is not a block device."
            fi

          #  check_dependencies
            setup_workspace
            build_busybox
            create_initramfs_content
            build_kernel
            install_to_uefi_target "${TARGET_USB_DEV}"
            log "Flashing complete. You can now safely eject ${TARGET_USB_DEV} and boot from it."
            ;;
        *)
            usage
            ;;
    esac

    log "Done."
}

main "$@"

Offline

#2 2025-07-02 21:40:44

unixman
Member
Registered: 2015-03-12
Posts: 182

Re: trying to build an minimal UEFI os but failing in VGA output

UEFI dont support VGA when booting as native.(no CMS).
you have to resort GOP. (graphics output protocol: an UEFI thingie:)

Offline

Board footer

Powered by FluxBB