Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions initrd/bin/config-gui.sh
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,9 @@ while true; do
exit 0
;;
"b")
#Change /boot device
CURRENT_OPTION="$(load_config_value CONFIG_BOOT_DEV)"
if ! fdisk -l 2>/dev/null | grep "Disk /dev/" | cut -f2 -d " " | cut -f1 -d ":" >/tmp/disklist.txt; then
if ! list_block_devices >/tmp/disklist.txt; then
whiptail_error --title 'ERROR: No bootable devices found' \
--msgbox " $ERROR\n\n" 0 80
exit 1
Expand Down Expand Up @@ -214,8 +215,9 @@ while true; do
fi
;;
"R")
#Change the root device for hashing
CURRENT_OPTION="$(load_config_value CONFIG_ROOT_DEV)"
fdisk -l 2>/dev/null | grep "Disk /dev/" | cut -f2 -d " " | cut -f1 -d ":" >/tmp/disklist.txt
list_block_devices >/tmp/disklist.txt
# filter out extraneous options
>/tmp/root_device_list.txt
for i in $(cat /tmp/disklist.txt); do
Expand Down
2 changes: 1 addition & 1 deletion initrd/bin/oem-factory-reset
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ select_thumb_drive_for_key_material() {
if [ $(cat /tmp/usb_disk_list | wc -l) -gt 0 ] &&
file_selector --show-size "/tmp/usb_disk_list" "Select USB device to partition" &&
[ -n "$FILE" ]; then
# Obtain size of thumb drive to be wiped with fdisk
# Obtain size of selected thumb drive in bytes
disk_size_bytes="$(blockdev --getsize64 "$FILE")"
if [ "$disk_size_bytes" -lt "$((128 * 1024 * 1024))" ]; then
warn "Thumb drive size is less than 128MB!"
Expand Down
6 changes: 5 additions & 1 deletion initrd/bin/oem-system-info-xx30
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ kernel=$(uname -s -r)

FB_OPTIONS=""
if whiptail --version | grep "fbwhiptail"; then FB_OPTIONS="--text-size 12"; fi

# Build disk information using shared sysfs helper
disk_info="$(disk_info_sysfs)"

# make sure we know the EC version too, populate if not already set
if [ -z "$EC_VER" ]; then
EC_VER=$(ec_version)
Expand All @@ -60,4 +64,4 @@ ec_ver_line=""
[ -n "$EC_VER" ] && ec_ver_line="\nEC_VER: ${EC_VER}"

whiptail_type $BG_COLOR_MAIN_MENU $FB_OPTIONS --title 'System Info' \
--msgbox "${BOARD_NAME}\nFW_VER: ${FW_VER}${ec_ver_line}\nKernel: ${kernel}\nCPU: ${cpustr} RAM: ${memtotal} GB $battery_status\n$(fdisk -l | grep -e '/dev/sd.:' -e '/dev/nvme.*:' | sed 's/B,.*/B/')\n\n$(cat /tmp/devices_usb_pci)" 0 80
--msgbox "${BOARD_NAME}\nFW_VER: ${FW_VER}${ec_ver_line}\nKernel: ${kernel}\nCPU: ${cpustr} RAM: ${memtotal} GB $battery_status\n${disk_info}\n$(cat /tmp/devices_usb_pci)" 0 80
29 changes: 22 additions & 7 deletions initrd/bin/root-hashes-gui.sh
Original file line number Diff line number Diff line change
Expand Up @@ -164,21 +164,29 @@ check_root_checksums() {
open_block_device_lvm() {
TRACE_FUNC
local VG="$1"
local LV
local MAPPER_VG

if ! lvm vgchange -ay "$VG"; then
DEBUG "Can't open LVM VG: $VG"
return 1
fi

# Use the LV 'root'. This is the default name used by Qubes. There's no
# way to configure this at the moment.
if ! [ -e "/dev/mapper/$VG-root" ]; then
# Use the LV 'root'. This is the default name used by Qubes. Try both the
# canonical /dev/<vg>/<lv> path and mapper path (with dash escaping).
LV="/dev/$VG/root"
if ! [ -e "$LV" ]; then
MAPPER_VG="${VG//-/--}"
LV="/dev/mapper/$MAPPER_VG-root"
fi

if ! [ -e "$LV" ]; then
DEBUG "LVM volume group does not have 'root' logical volume"
return 1
fi

# Use the root LV now
open_block_device_layers "/dev/mapper/$VG-root"
open_block_device_layers "$LV"
}

# Open a LUKS device, then continue looking for more layers.
Expand Down Expand Up @@ -269,9 +277,16 @@ open_root_device_no_clean_up() {
close_block_device_lvm() {
TRACE_FUNC
local VG="$1"
local LV
local MAPPER_VG

# We always use the LV 'root' currently. Try canonical and mapper paths.
LV="/dev/$VG/root"
if ! [ -e "$LV" ]; then
MAPPER_VG="${VG//-/--}"
LV="/dev/mapper/$MAPPER_VG-root"
fi

# We always use the LV 'root' currently
local LV="/dev/mapper/$VG-root"
if [ -e "$LV" ]; then
close_block_device_layers "$LV"
fi
Expand Down Expand Up @@ -367,7 +382,7 @@ detect_root_device()
fi

# generate list of possible boot devices
fdisk -l 2>/dev/null | grep "Disk /dev/" | cut -f2 -d " " | cut -f1 -d ":" > /tmp/disklist
list_block_devices > /tmp/disklist

# filter out extraneous options
> /tmp_root_device_list
Expand Down
115 changes: 92 additions & 23 deletions initrd/etc/functions
Original file line number Diff line number Diff line change
Expand Up @@ -802,24 +802,77 @@ enable_usb_storage() {

device_has_partitions() {
local DEVICE="$1"
# fdisk normally says "doesn't contain a valid partition table" for
# devices that lack a partition table - except for FAT32.
#
# FAT32 devices have a volume boot record that looks enough like an MBR
# to satisfy fdisk. In that case, fdisk prints a partition table header
# but no partitions.
#
# This check covers that: [ $(fdisk -l "$b" | wc -l) -eq 5 ]
# In both cases the output is 5 lines: 3 about device info, 1 empty line
# and the 5th will be the table header or the invalid message.
local DISK_DATA=$(fdisk -l "$DEVICE" 2>/dev/null)
if echo "$DISK_DATA" | grep -q "doesn't contain a valid partition table" ||
[ "$(echo "$DISK_DATA" | wc -l)" -eq 5 ]; then
# No partition table
# Check if device has any partitions by checking sysfs
# A device with partitions will have entries like /sys/block/sda/sda1, /sys/block/vda/vda1, etc
local device_name=$(basename "$DEVICE")

if [ ! -e "/sys/block/$device_name" ]; then
# Device doesn't exist
return 1
fi
# There is a partition table
return 0

# Count partitions - handle nvme partition naming (nvme0n1p1) and traditional (sda1, vda1, hda1)
if [ -n "$(ls -1 /sys/block/$device_name/ 2>/dev/null | grep -E "^${device_name}(p)?[0-9]")" ]; then
# There is a partition table
return 0
fi
# No partition table
return 1
}

# List all block devices using sysfs
# Outputs one device path per line (e.g., /dev/sda, /dev/vda, /dev/nvme0n1)
list_block_devices() {
TRACE_FUNC
for dev in /sys/block/sd* /sys/block/nvme* /sys/block/vd* /sys/block/hd*; do
if [ -e "$dev" ]; then
echo "/dev/$(basename "$dev")"
fi
done | sort
}

# Build displayable disk information using sysfs (vs current busybox's 2tb limit per https://bugs.busybox.net/show_bug.cgi?id=16276)
# Output format: "Disk /dev/<name>: <GB> GB" per line
disk_info_sysfs() {
TRACE_FUNC
local disk_info=""
DEBUG "disk_info_sysfs: Starting disk enumeration"
for dev in /sys/block/sd* /sys/block/nvme* /sys/block/vd* /sys/block/hd*; do
if [ -e "$dev" ]; then
local devname=$(basename "$dev")
DEBUG "disk_info_sysfs: Found device $dev (devname=$devname)"
local size_bytes=$(cat "$dev/size" 2>/dev/null)
DEBUG "disk_info_sysfs: /dev/${devname} reports size_bytes=$size_bytes sectors from $dev/size"
if [ -n "$size_bytes" ] && [ "$size_bytes" -gt 0 ]; then
# Determine sector size for this device from sysfs; prefer hw_sector_size
local sector_size=512
if [ -r "$dev/queue/hw_sector_size" ]; then
sector_size=$(cat "$dev/queue/hw_sector_size" 2>/dev/null || echo 512)
DEBUG "disk_info_sysfs: /dev/${devname} using hw_sector_size=$sector_size from $dev/queue/hw_sector_size"
elif [ -r "$dev/queue/logical_block_size" ]; then
sector_size=$(cat "$dev/queue/logical_block_size" 2>/dev/null || echo 512)
DEBUG "disk_info_sysfs: /dev/${devname} using logical_block_size=$sector_size from $dev/queue/logical_block_size"
else
DEBUG "disk_info_sysfs: /dev/${devname} using default sector_size=$sector_size (no queue info available)"
fi
# Convert from sectors * sector_size to bytes, then to decimal GB.
#
# Explanation of the constants:
# - We divide by 1,000,000,000 (1000000000) to report decimal GB (10^9 bytes),
# which matches the historical output used elsewhere in Heads.
# - Shell arithmetic is integer-only, so to round to the nearest GB we add
# half the divisor (500,000,000) before dividing. This implements
# rounding instead of truncation.
# If you prefer binary GiB (1024^3), replace the divisor and half-divisor
# with 1073741824 and 536870912 respectively, or use `awk`/`printf`
# for fractional output.
local size_gb=$(((size_bytes * sector_size + 500000000) / 1000000000))
disk_info="${disk_info}Disk /dev/${devname}: ${size_gb} GB\n"
DEBUG "disk_info_sysfs: /dev/${devname} calculated as ${size_gb} GB (${size_bytes} sectors * ${sector_size} bytes/sector = $((size_bytes * sector_size)) bytes)"
Comment on lines +844 to +871
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In disk_info_sysfs(), /sys/block//size is a count of 512-byte sectors (same units as blockdev --getsz), not “sectors of hw_sector_size”. Multiplying it by hw_sector_size/logical_block_size will over-report sizes (e.g., 4Kn devices) and can overflow sooner. Consider using bytes from blockdev --getsize64 "/dev/$devname" (still avoids busybox fdisk), or treat size as 512-byte sectors and multiply by 512 unconditionally.

Copilot uses AI. Check for mistakes.
fi
fi
done
echo -n "$disk_info"
}

list_usb_storage() {
Expand Down Expand Up @@ -1278,12 +1331,19 @@ is_gpt_bios_grub() {

NUMBER="${BASH_REMATCH[1]}"

# Now we know the device and partition number, get the type. This is
# specific to GPT disks, MBR disks are shown differently by fdisk.
TRACE "$PART_DEV is partition $NUMBER of $DEVICE"
if [ "$(fdisk -l "/dev/$DEVICE" 2>/dev/null | awk '$1 == '"$NUMBER"' {print $5}')" == grub ]; then
return 0
# Check partition type using sysfs if available, otherwise check for grub type
# For GPT disks, check /sys/class/block/<dev>/<partition>/uevent for PARTTYPENAME
local part_sys="/sys/class/block/$DEVICE/$(basename "$PART_DEV")"
if [ -e "$part_sys/uevent" ]; then
if grep -q "PARTTYPENAME=BIOS boot" "$part_sys/uevent"; then
TRACE "$PART_DEV is a GPT BIOS grub partition"
return 0
fi
fi

# Fallback: try to detect using other sysfs attributes if available
# For MBR disks, we would need to check partition type differently
Comment on lines +1334 to +1345
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_gpt_bios_grub() checks for "PARTTYPENAME=BIOS boot" in sysfs uevent, but the kernel typically exports PARTTYPE (the type GUID) rather than a human-readable PARTTYPENAME (usually provided by udev). In initrd this will likely never match, so BIOS-boot partitions may no longer be filtered reliably. Suggest checking PARTTYPE against the BIOS boot GUID (21686148-6449-6E6F-744E-656564454649) and/or keeping the previous fdisk-based fallback; also update the comment that mentions a fallback that no longer exists.

Suggested change
# Check partition type using sysfs if available, otherwise check for grub type
# For GPT disks, check /sys/class/block/<dev>/<partition>/uevent for PARTTYPENAME
local part_sys="/sys/class/block/$DEVICE/$(basename "$PART_DEV")"
if [ -e "$part_sys/uevent" ]; then
if grep -q "PARTTYPENAME=BIOS boot" "$part_sys/uevent"; then
TRACE "$PART_DEV is a GPT BIOS grub partition"
return 0
fi
fi
# Fallback: try to detect using other sysfs attributes if available
# For MBR disks, we would need to check partition type differently
# Check partition type using sysfs if available.
# For GPT disks, check /sys/class/block/<dev>/<partition>/uevent for PARTTYPE
# matching the BIOS boot GUID (21686148-6449-6E6F-744E-656564454649). Some
# environments may also expose PARTTYPENAME=BIOS boot via udev.
local part_sys="/sys/class/block/$DEVICE/$(basename "$PART_DEV")"
if [ -e "$part_sys/uevent" ]; then
# Legacy/udev-based check: human-readable type name
if grep -q "PARTTYPENAME=BIOS boot" "$part_sys/uevent"; then
TRACE "$PART_DEV is a GPT BIOS grub partition (PARTTYPENAME)"
return 0
fi
# Preferred check: kernel-exported type GUID
if grep -qi "PARTTYPE=21686148-6449-6E6F-744E-656564454649" "$part_sys/uevent"; then
TRACE "$PART_DEV is a GPT BIOS grub partition (PARTTYPE GUID)"
return 0
fi
fi

Copilot uses AI. Check for mistakes.
DEBUG "$PART_DEV - unable to confirm it's a bios-grub partition via sysfs"
return 1
}

Expand Down Expand Up @@ -1344,7 +1404,16 @@ mount_possible_boot_device() {
detect_boot_device() {
TRACE_FUNC
local devname
# unmount /boot to be safe
local mounted_boot_dev

# If /boot is already mounted and looks valid, reuse it directly.
mounted_boot_dev="$(awk '$2 == "/boot" {print $1; exit}' /proc/mounts)"
if [ -n "$mounted_boot_dev" ] && ls -d /boot/grub* >/dev/null 2>&1; then
CONFIG_BOOT_DEV="$mounted_boot_dev"
return 0
fi

# unmount /boot to be safe before probe-based detection
cd / && umount /boot 2>/dev/null

# check $CONFIG_BOOT_DEV if set/valid
Expand All @@ -1354,7 +1423,7 @@ detect_boot_device() {
fi

# generate list of possible boot devices
fdisk -l 2>/dev/null | grep "Disk /dev/" | cut -f2 -d " " | cut -f1 -d ":" >/tmp/disklist
list_block_devices >/tmp/disklist

# Check each possible boot device
for i in $(cat /tmp/disklist); do
Expand Down
8 changes: 5 additions & 3 deletions initrd/etc/gui_functions
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ display_block_device_size() {
local block_dev disk_size_bytes
block_dev="$1"

# Obtain size of thumb drive to be wiped with fdisk
# Obtain size of the selected block device in bytes
if ! disk_size_bytes="$(blockdev --getsize64 "$block_dev")"; then
exit 1
fi
Expand Down Expand Up @@ -178,6 +178,9 @@ show_system_info() {
cpustr=$(cat /proc/cpuinfo | grep 'model name' | uniq | sed -r 's/\(R\)//;s/\(TM\)//;s/CPU //;s/model name.*: //')
kernel=$(uname -s -r)

# Get disk information using the shared sysfs helper from functions
local disk_info="$(disk_info_sysfs)"

local ec_ver_line=""
[ -n "$EC_VER" ] && ec_ver_line="
EC_VER: ${EC_VER}"
Expand All @@ -191,8 +194,7 @@ show_system_info() {
Microcode: $(cat /proc/cpuinfo | grep microcode | uniq | cut -d':' -f2 | tr -d ' ')
RAM: ${memtotal} GB
$battery_status
$(fdisk -l 2>/dev/null | grep -e '/dev/sd.:' -e '/dev/nvme.*:' | sed 's/B,.*/B/')
"
${disk_info}"

local msgbox_rm_tabs=$(echo "$msgbox" | tr -d "\t")

Expand Down