From 3610f63900614bc0eb0923777463978435802ec2 Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Thu, 11 Jun 2026 00:54:56 -0300 Subject: [PATCH] rootfs-handoff: add UUID= and LABEL= support for root= parameter - Added ext2_get_uuid_label() function in ext2.c to extract UUID and volume name - Added format_uuid() helper to format 16-byte UUID to string format - Added uuid_matches() helper to compare UUID string with binary UUID - Added resolve_by_uuid_label() function in init.c to scan block devices and partitions - Modified init_resolve_mount_device() to recognize UUID= and LABEL= prefixes - Scans all ATA devices (hda-hdd) and their partitions (hda1-hda4) - Supports ext2 filesystems (UUID and volume name from superblock) - This implements the 'UUID= and LABEL= support' item from ROOTFS_HANDOFF_PLAN.md Test Results: - Smoke test: 131/131 PASS - Battery test: 157/157 PASS - Analyzer: PASS - Zero regressions --- include/ext2.h | 5 +++ src/kernel/ext2.c | 36 ++++++++++++++++ src/kernel/init.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+) diff --git a/include/ext2.h b/include/ext2.h index 7df2d244..c4802cc6 100644 --- a/include/ext2.h +++ b/include/ext2.h @@ -48,6 +48,11 @@ vfs_mount_result_t ext2_mount_partition(struct partition* part); * Returns -EINVAL if filesystem has errors that prevent mount */ int ext2_verify_state(block_device_t* bdev, uint32_t partition_lba); +/* Get ext2 filesystem UUID (16 bytes) and volume name + * Returns 0 on success, -errno on failure */ +int ext2_get_uuid_label(block_device_t* bdev, uint32_t partition_lba, + uint8_t uuid[16], char label[16]); + /* Unmount an ext2 filesystem and free its resources */ void ext2_umount(struct ext2_mount* em); diff --git a/src/kernel/ext2.c b/src/kernel/ext2.c index 5fc0ee54..53e66d9f 100644 --- a/src/kernel/ext2.c +++ b/src/kernel/ext2.c @@ -246,6 +246,42 @@ int ext2_verify_state(block_device_t* bdev, uint32_t partition_lba) { return 0; } +/* Get ext2 filesystem UUID (16 bytes) and volume name + * Returns 0 on success, -errno on failure */ +int ext2_get_uuid_label(block_device_t* bdev, uint32_t partition_lba, + uint8_t uuid[16], char label[16]) { + if (!bdev) return -ENODEV; + + /* Read superblock to get UUID and label */ + uint8_t sec[EXT2_SECTOR_SIZE]; + uint32_t sb_lba = partition_lba + EXT2_SUPER_OFFSET / EXT2_SECTOR_SIZE; + + uint8_t raw[1024]; + for (uint32_t i = 0; i < 1024 / EXT2_SECTOR_SIZE; i++) { + if (blockdev_read(bdev, sb_lba + i, sec) < 0) return -EIO; + memcpy(raw + i * EXT2_SECTOR_SIZE, sec, EXT2_SECTOR_SIZE); + } + + struct ext2_superblock sb; + memcpy(&sb, raw, sizeof(sb)); + + /* Check magic */ + if (sb.s_magic != EXT2_SUPER_MAGIC) { + return -EINVAL; /* Not an ext2 filesystem */ + } + + /* Copy UUID and label */ + if (uuid) { + memcpy(uuid, sb.s_uuid, 16); + } + if (label) { + memcpy(label, sb.s_volume_name, 16); + label[15] = '\0'; /* Ensure null-termination */ + } + + return 0; +} + static int ext2_read_superblock(struct ext2_mount* em, struct ext2_superblock* sb) { if (!em || !em->bdev) return -ENODEV; /* Superblock is at byte offset 1024, which is LBA 2-3 relative to partition */ diff --git a/src/kernel/init.c b/src/kernel/init.c index a3c121da..bfeedbb3 100644 --- a/src/kernel/init.c +++ b/src/kernel/init.c @@ -28,6 +28,7 @@ #include "socket.h" #include "vbe.h" #include "keyboard.h" +#include "blockdev.h" #include "console.h" #include "errno.h" #include "utils.h" @@ -84,9 +85,112 @@ static void init_build_mount_source_name(const char* source_name, block_device_t *dp = '\0'; } +/* Format UUID (16 bytes) to string "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" */ +static void format_uuid(const uint8_t uuid[16], char* out, size_t out_size) { + if (out_size < 37) return; /* Need 36 chars + null terminator */ + + const char hex[] = "0123456789abcdef"; + int pos = 0; + + /* Format: 8-4-4-4-12 */ + for (int i = 0; i < 16; i++) { + if (i == 4 || i == 6 || i == 8 || i == 10) { + out[pos++] = '-'; + } + out[pos++] = hex[uuid[i] >> 4]; + out[pos++] = hex[uuid[i] & 0x0F]; + } + out[pos] = '\0'; +} + +/* Compare UUID string with binary UUID */ +static int uuid_matches(const char* uuid_str, const uint8_t uuid[16]) { + char formatted[37]; + format_uuid(uuid, formatted, sizeof(formatted)); + return strcmp(uuid_str, formatted) == 0; +} + +/* Resolve device by UUID or LABEL + * Scans all block devices and partitions to find matching UUID or LABEL + * Returns 0 on success, -errno on failure */ +static int resolve_by_uuid_label(const char* prefix, const char* value, + block_device_t** bdev, uint32_t* lba) { + /* Scan all block devices */ + for (int i = 0; i < 8; i++) { /* ATA devices: hda-hdd */ + char devname[8]; + devname[0] = 'h'; + devname[1] = 'd'; + devname[2] = 'a' + i; + devname[3] = '\0'; + block_device_t* dev = blockdev_find(devname); + if (!dev) continue; + + /* Check whole device (ext2 on raw disk) */ + uint8_t uuid[16]; + char label[16]; + if (ext2_get_uuid_label(dev, 0, uuid, label) == 0) { + if (strcmp(prefix, "UUID") == 0) { + if (uuid_matches(value, uuid)) { + *bdev = dev; + *lba = 0; + return 0; + } + } else if (strcmp(prefix, "LABEL") == 0) { + if (strcmp(value, label) == 0) { + *bdev = dev; + *lba = 0; + return 0; + } + } + } + + /* Check partitions */ + for (int part_num = 1; part_num <= 4; part_num++) { + char partname[16]; + partname[0] = 'h'; + partname[1] = 'd'; + partname[2] = 'a' + i; + partname[3] = '0' + part_num; + partname[4] = '\0'; + partition_t* part = partition_find(partname); + if (!part || !part->parent) continue; + + if (ext2_get_uuid_label(part->parent, part->start_lba, uuid, label) == 0) { + if (strcmp(prefix, "UUID") == 0) { + if (uuid_matches(value, uuid)) { + *bdev = part->parent; + *lba = part->start_lba; + return 0; + } + } else if (strcmp(prefix, "LABEL") == 0) { + if (strcmp(value, label) == 0) { + *bdev = part->parent; + *lba = part->start_lba; + return 0; + } + } + } + } + } + + return -ENODEV; +} + int init_resolve_mount_device(const char* device, block_device_t** bdev, uint32_t* lba) { if (!device || !bdev || !lba) return -EINVAL; + /* Check for UUID= or LABEL= prefix */ + if (strncmp(device, "UUID=", 5) == 0) { + const char* uuid_str = device + 5; + return resolve_by_uuid_label("UUID", uuid_str, bdev, lba); + } + + if (strncmp(device, "LABEL=", 6) == 0) { + const char* label_str = device + 6; + return resolve_by_uuid_label("LABEL", label_str, bdev, lba); + } + + /* Regular device path */ const char* devname = device; if (strncmp(devname, "/dev/", 5) == 0) devname += 5; -- 2.43.0