build-rootfs: Transition from custom GRUB config to upstream standard (update-grub)#108
build-rootfs: Transition from custom GRUB config to upstream standard (update-grub)#108bjordiscollaku merged 10 commits intomainfrom
Conversation
…rkflow This commit replaces the static, manual generation of /boot/grub.cfg with the standard Debian update-grub mechanism. This change ensures that the bootloader configuration is automatically synchronized with installed kernels and adheres to standard distribution practices. Key Changes: * Standard Implementation: Replaced the manual file write of /boot/grub.cfg with the generation of /etc/default/grub followed by execution of update-grub. * Dependency Management: Added grub-common and grub2-common to the debootstrap package list to provide the necessary tools (grub-mkconfig, grub-probe) inside the chroot. * Correct Recovery Mode: Configured critical hardware arguments (console, root label, EFI) in GRUB_CMDLINE_LINUX. Unlike the previous single-entry manual config, this ensures that auto-generated "Recovery Mode" entries retain necessary drivers and serial console output. * Filesystem Addressing: Set GRUB_DISABLE_LINUX_UUID=true to force root=LABEL=system, maintaining portability for the generic rootfs image. Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
This commit refactors the GRUB configuration logic by moving the generation of /etc/default/grub from the chroot environment to the host context. Generating the configuration file inside the nested chroot command string caused shell quoting conflicts and prevented the reliable writing of the config file (specifically affecting heredoc termination and variable escaping). Key Changes: * Host-Side Generation: Extracted the config writing logic to a new pre-chroot step (Step 7.5). It now uses a quoted heredoc (cat <<'EOF') to write the file directly into the mounted rootfs. * Stability: This ensures that variables and backticks (e.g., for `lsb_release`) are written literally to the file and not interpreted by the host shell. * Clean Execution: The chroot step (Step 8) is now simplified to strictly run `update-grub`, relying on the correctly pre-seeded configuration file. Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
…ilure This commit resolves a build failure where `grub-mkconfig` (invoked by `update-grub`) exited with "Directory nonexistent". The error occurred because the `/boot/grub` directory structure was not present in the rootfs prior to the execution of `update-grub`. The transition to host-side configuration requires explicitly creating these artifact directories, as they are not guaranteed to be populated by `debootstrap` at this stage. Key Changes: * Explicitly added `mkdir -p` for `/boot/grub` and `/etc/default` in Step 7.5. * Ensures the destination directory exists before the host writes the configuration file or the chroot attempts to generate the boot menu.
This commit implements a post-processing stage for the GRUB configuration to resolve "host contamination" issues. When `update-grub` runs inside the chroot, it probes the build host's hardware, incorrectly baking the host's filesystem UUIDs and block device paths (e.g., `/dev/nvme0n1p1`) into the target image. This patch scrubs these host-specific artifacts to ensure the generated rootfs is generic and portable. Key Changes: - Enforce Label-Based Search: Replaces the standard `search --fs-uuid` command with `search --label system` via sed. This ensures the bootloader can locate the kernel partition regardless of the underlying storage UUID. - Sanitize Kernel Command Line: Strips the host-detected `root=/dev/xxx` parameter. This prevents conflicts with the intended `root=LABEL=system` argument defined in `/etc/default/grub`. - Relative Compatibility Symlink: Updates the legacy `/boot/grub.cfg` symlink to use a relative path (`grub/grub.cfg`) instead of an absolute one, ensuring correct resolution on both the target and the build host. Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
Remove the manual kernel version extraction logic (kernel_ver calculation) from Step 8. This variable was previously required for manually constructing grub.cfg menu entries. With the transition to the standard `update-grub` workflow, the kernel version is automatically detected by scanning /boot, making this explicit parsing redundant and unused. Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
This commit removes the explicit `update-grub` call from the build sequence, delegating bootloader configuration entirely to the kernel package's installation hooks. The generation of `grub.cfg` is guaranteed by the kernel package's `postinst` script, which executes `update-grub` immediately following `update-initramfs`. Eliminating the secondary invocation in the build script reduces redundancy while maintaining reliance on standard package management lifecycle events to populate the bootloader configuration prior to image finalization. Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
This commit configures the GRUB bootloader to simultaneously output its menu to both the serial port and the attached display. By default, `update-grub` prioritizes graphical terminals (gfxterm) or auto-detects a single output, often rendering the menu invisible on headless serial connections or embedded displays without full driver support. This change explicitly sets `GRUB_TERMINAL="serial console"`, ensuring the menu is accessible via the serial debug port (115200 baud) and the native text-mode console on HDMI/DP. Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
This commit introduces a platform-specific bootloader configuration stage for ARM64 Debian targets. Since the standard GRUB generation logic in the target environment does not natively support automated DTB loading via variables, this change implements a surgical post-processing step at the end of the chroot phase: 1. Dynamic Resolution: Uses a multi-path search (/usr/lib and /lib/firmware) to locate the 'glymur-crd.dtb' platform description. 2. Visibility: Establishes a stable '/boot/dtb' symlink to ensure the bootloader can access hardware descriptions within its filesystem scope. 3. Injection: Directly patches the generated 'grub.cfg' to include the 'devicetree' directive following the 'initrd' load sequence. This approach ensures hardware-specific initialization is successful on first boot while maintaining compatibility with the host's existing distribution-specific GRUB scripts. Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
| echo \"[INFO][CHROOT] Platform DTB resolved: \$DTB_PATH\" | ||
|
|
||
| # Ensure DTB is accessible in the bootloader's filesystem scope | ||
| ln -sf \"\$DTB_PATH\" /boot/dtb |
There was a problem hiding this comment.
(Not sure why first comment is not showing up, sorry for the dup)
/boot/dtb can only exist once; GRUB config generation will generate entries for each kernel, you want to tap into that to generate entries for each kernel with a devicetree line from the right kernel.
| echo '[INFO][CHROOT] Debian target detected. Configuring platform Device Tree...' | ||
|
|
||
| # Locate the platform Device Tree Blob (DTB) in standard library or firmware paths | ||
| DTB_PATH=\$(find /usr/lib /lib/firmware -name \"glymur-crd.dtb\" -print -quit) |
There was a problem hiding this comment.
Why hardcode glymur-crd.dtb? How will this image work on other systems?
There was a problem hiding this comment.
Conditional devicetree injection is to temporarily support glymur enablement in CI/nightly, up until multi-dtb (combined or FIT) dtb.bin is supported on glymur platform, just like in Hamoa IoT, in which case conditional injection of this hardcoded devicetree path in grub menuentry completely vanishes, alongside the "ln -sf $DTB_PATH /boot/dtb".
Result is then devicetree agnostic generalized grub config generated straight from update-grub (which runs as part of postinst script of the kernel deb package).
Overview
This PR completely refactors the bootloader configuration logic in
build-rootfs.sh. It abandons the manual, static construction ofgrub.cfgin favor of the standard Debianupdate-grubmechanism. This ensures robust compatibility with upstream kernel packages and automated menu generation.The PR encompasses the definition of critical boot defaults (Step 7.5), the isolation of host vs. target environment variables, and a post-processing stage to ensure the generated image remains generic and portable despite being built on a host machine.
Detailed Changes
1. Configuration & Defaults (Step 7.5)
/etc/default/grubprior to the chroot phase.GRUB_CMDLINE_LINUXwith critical hardware settings (earlycon,console=ttyMSM0,efi=noruntime) ensuring these apply to both Normal and Recovery boot modes.GRUB_DISABLE_LINUX_UUID=trueand enforcedroot=LABEL=system. This prepares the config for generic booting, ensuring the kernel does not rely on specific partition block UUIDs.cat <<'EOF') for writing the config file. This ensures that backticked commands (like`lsb_release`) are written literally to the file for execution inside the target, preventing accidental expansion/execution by the build host shell.mkdir -pcommands for/boot/gruband/etc/default. This resolves race conditions whereupdate-grub(triggered by package installs) would fail due to missing directory structures.2. Standardization & Lifecycle (Step 8)
cat > grub.cfglogic with the standardupdate-grubtoolchain.grub-common,grub2-common, andlsb-releaseto the debootstrap seed list to ensure generation tools are present in the baseline rootfs.kernel_ver) and the explicitupdate-grubcall in Step 8. We now delegate configuration generation entirely to the kernel package'spostinsthook, which executesupdate-grubimmediately after installation. This aligns the build process with standard Debian package lifecycle events.3. Post-Processing & Sanitization
Because
update-grubruns inside a chroot on the build host, it inherently "leaks" host-specific details. We added a sanitization layer to scrub these artifacts:sedlogic to strip host-detected UUID searches (search --fs-uuid ...) and replace them withsearch --label system. This ensures the bootloader can locate the kernel on any storage medium (SD, eMMC, NVMe)./dev/nvme0n1p1) thatgrub-probeincorrectly detects from the build server, strictly enforcing the genericroot=LABEL=systemargument./boot/grub.cfgcompatibility link to use a relative path (grub/grub.cfg) instead of an absolute one, ensuring correct file resolution both during runtime and when the rootfs is mounted on a host machine for inspection.