bootman: improve filesystem detection

Improve the internal filesystem detection, with these changes we
can reuse this code elsewhere and be more efficient - other areas
needing the filesystem knowledge can use this mapping strategies
adding a more precise and centralized code to that.

This patch also makes sure to keep tests and filesystem checks more
consistent.

When mounting we were assuming the /boot filesystem to always be
vfat, with this code now we can have /boot partitions with whatever
filesystem we support (for now: vfat, ext[2-4]).

Signed-off-by: Leandro Dorileo <leandro.maciel.dorileo@intel.com>
This commit is contained in:
Leandro Dorileo
2019-09-12 12:12:28 -07:00
committed by William Douglas
parent ef65b290de
commit 486486e19a
11 changed files with 142 additions and 57 deletions
+7 -1
View File
@@ -414,6 +414,7 @@ int mount_boot(BootManager *self, char **boot_directory)
autofree(char) *boot_dir = NULL;
int ret = -1;
char *root_base = NULL;
const char *fs_name = NULL;
if (!boot_directory) {
goto out;
@@ -481,7 +482,12 @@ int mount_boot(BootManager *self, char **boot_directory)
}
LOG_INFO("Mounting boot device %s at %s", root_base, boot_dir);
if (cbm_system_mount(root_base, boot_dir, "vfat", MS_MGC_VAL, "") < 0) {
fs_name = cbm_get_fstype_name(root_base);
CHECK_FATAL_GOTO(!fs_name, out, "Could not determine fstype of: %s",
root_base);
if (cbm_system_mount(root_base, boot_dir, fs_name, MS_MGC_VAL, "") < 0) {
LOG_FATAL("FATAL: Cannot mount boot device %s on %s: %s",
root_base,
boot_dir,
+7
View File
@@ -29,6 +29,13 @@ typedef enum {
BOOTLOADER_OPERATION_MAX = 1 << 5
} BootLoaderOperation;
typedef enum {
FSTYPE_VFAT = 1 << 0,
FSTYPE_EXT2 = 1 << 1,
FSTYPE_EXT3 = 1 << 2,
FSTYPE_EXT4 = 1 << 3,
} FilesystemType;
/**
* Maximum length for each component in a kernel identifier
*/
+5
View File
@@ -74,6 +74,11 @@ int detect_and_mount_boot(BootManager *self, char **boot_dir);
*/
int kernel_compare_reverse(const void *a, const void *b);
/**
* Given a boot_device returns the filesystem name, if unknown filesystem returns NULL.
*/
const char *cbm_get_fstype_name(const char *boot_device);
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
+108 -41
View File
@@ -28,6 +28,30 @@
#define CBM_BOOTVAR_TEST_MODE_VAR "CBM_BOOTVAR_TEST_MODE"
struct FilesystemMap {
char *name;
int id;
};
static const struct FilesystemMap _fsmap[] = {
{
.id = FSTYPE_VFAT,
.name = "vfat",
},
{
.id = FSTYPE_EXT2,
.name = "ext2",
},
{
.id = FSTYPE_EXT3,
.name = "ext3",
},
{
.id = FSTYPE_EXT4,
.name = "ext4",
},
};
void cbm_free_sysconfig(SystemConfig *config)
{
if (!config) {
@@ -39,51 +63,94 @@ void cbm_free_sysconfig(SystemConfig *config)
free(config);
}
int cbm_get_fstype(const char *boot_device)
static const struct FilesystemMap *cbm_find_fstype(const char *fsname)
{
int rc;
blkid_probe pr;
const char *data;
int ret = 0;
int i;
int length = sizeof(_fsmap) / sizeof(struct FilesystemMap);
for (i = 0; i < length; i++) {
const struct FilesystemMap *curr = &_fsmap[i];
if (!strcmp(curr->name, fsname)) {
return curr;
}
}
return NULL;
}
static const struct FilesystemMap *cbm_get_fstype(const char *boot_device)
{
autofree(char) *fsname = NULL;
const struct FilesystemMap *fs;
/* Test suite will set the CBM_TEST_FSTYPE env var and inform the wanted fstype */
char *test_mode_fs_type_env = getenv("CBM_TEST_FSTYPE");
if (test_mode_fs_type_env && !strncmp(test_mode_fs_type_env, "EXTFS", 5)) {
return BOOTLOADER_CAP_EXTFS;
} else if (test_mode_fs_type_env && !strncmp(test_mode_fs_type_env, "FATFS", 5)) {
fsname = getenv("CBM_TEST_FSTYPE");
if (fsname) {
fsname = strdup(fsname);
} else {
int rc;
blkid_probe pr;
const char *tmp;
pr = blkid_new_probe_from_filename(boot_device);
if (!pr) {
LOG_ERROR("%s: failed to create a new libblkid probe",
boot_device);
exit(EXIT_FAILURE);
}
blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_TYPE);
rc = blkid_do_safeprobe(pr);
if (rc != 0) {
LOG_ERROR("%s: blkid_do_safeprobe() failed", boot_device);
exit(EXIT_FAILURE);
}
rc = blkid_probe_lookup_value(pr, "TYPE", &tmp, NULL);
if (rc != 0 || tmp == NULL || strlen(tmp) == 0) {
LOG_ERROR("%s: blkid_probe_lookup_value() failed", boot_device);
exit(EXIT_FAILURE);
}
fsname = strdup(tmp);
if (fsname == NULL) {
DECLARE_OOM();
exit(EXIT_FAILURE);
}
blkid_free_probe(pr);
}
fs = cbm_find_fstype(fsname);
CHECK_DBG_RET_VAL(!fs, NULL, "Failed to find fstype for: %s(%s)", boot_device, fsname);
return fs;
}
const char *cbm_get_fstype_name(const char *boot_device)
{
const struct FilesystemMap *fs = cbm_get_fstype(boot_device);
CHECK_DBG_RET_VAL(!fs, NULL, "Unknown Filesystem of: %s", boot_device);
return fs->name;
}
int cbm_get_filesystem_cap(const char *boot_device)
{
const struct FilesystemMap *fs = NULL;
fs = cbm_get_fstype(boot_device);
CHECK_DBG_RET_VAL(!fs, 0, "Could not find filesystem map for: %s", boot_device);
switch (fs->id) {
case FSTYPE_VFAT:
return BOOTLOADER_CAP_FATFS;
case FSTYPE_EXT2:
case FSTYPE_EXT3:
case FSTYPE_EXT4:
return BOOTLOADER_CAP_EXTFS;
default:
return 0;
}
pr = blkid_new_probe_from_filename(boot_device);
if (!pr) {
LOG_ERROR("%s: failed to create a new libblkid probe",
boot_device);
exit(EXIT_FAILURE);
}
blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_TYPE);
rc = blkid_do_safeprobe(pr);
if (rc != 0) {
LOG_ERROR("%s: blkid_do_safeprobe() failed", boot_device);
exit(EXIT_FAILURE);
}
rc = blkid_probe_lookup_value(pr, "TYPE", &data, NULL);
if (rc != 0) {
LOG_ERROR("%s: blkid_probe_lookup_value() failed", boot_device);
exit(EXIT_FAILURE);
}
if ((strcmp(data, "ext2") == 0) ||
(strcmp(data, "ext3") == 0) ||
(strcmp(data, "ext4") == 0))
ret = BOOTLOADER_CAP_EXTFS;
else if (strcmp(data, "vfat") == 0)
ret = BOOTLOADER_CAP_FATFS;
blkid_free_probe(pr);
return ret;
}
static void cmb_inspect_root_native(SystemConfig *c, char *realp) {
@@ -189,7 +256,7 @@ SystemConfig *cbm_inspect_root(const char *path, bool image_mode)
c->wanted_boot_mask |= BOOTLOADER_CAP_GPT;
/* determine fstype of the boot_device */
c->wanted_boot_mask |= cbm_get_fstype(c->boot_device);
c->wanted_boot_mask |= cbm_get_filesystem_cap(c->boot_device);
}
c->root_device = cbm_probe_path(realp);
+1 -1
View File
@@ -434,7 +434,7 @@ int main(void)
setenv("CBM_BOOTVAR_TEST_MODE", "yes", 1);
/* Force detection of `fat` filesystem. */
setenv("CBM_TEST_FSTYPE", "FATFS", 1);
setenv("CBM_TEST_FSTYPE", "vfat", 1);
cbm_blkid_set_vtable(&BlkidTestOps);
cbm_system_set_vtable(&SystemTestOps);
+1 -1
View File
@@ -265,7 +265,7 @@ int main(void)
setenv("CBM_BOOTVAR_TEST_MODE", "yes", 1);
/* Force detection of `ext` filesystem. */
setenv("CBM_TEST_FSTYPE", "EXTFS", 1);
setenv("CBM_TEST_FSTYPE", "ext4", 1);
cbm_blkid_set_vtable(&blkid_ops);
cbm_system_set_vtable(&SystemTestOps);
+1 -1
View File
@@ -304,7 +304,7 @@ int main(void)
setenv("CBM_BOOTVAR_TEST_MODE", "yes", 1);
/* Force detection of `ext` filesystem. */
setenv("CBM_TEST_FSTYPE", "EXTFS", 1);
setenv("CBM_TEST_FSTYPE", "ext4", 1);
cbm_blkid_set_vtable(&blkid_ops);
cbm_system_set_vtable(&SystemTestOps);
+1 -1
View File
@@ -245,7 +245,7 @@ int main(void)
setenv("CBM_BOOTVAR_TEST_MODE", "yes", 1);
/* Force detection of `fat` filesystem. */
setenv("CBM_TEST_FSTYPE", "FATFS", 1);
setenv("CBM_TEST_FSTYPE", "vfat", 1);
s = core_suite();
sr = srunner_create(s);
+9 -9
View File
@@ -104,7 +104,7 @@ static void nuke_boot_device(struct PlaygroundConfig *config)
START_TEST(bootman_select_uefi_native_with_boot)
{
static PlaygroundConfig config = { "4.2.1-121.kvm", NULL, 0, .uefi = true };
setenv("CBM_TEST_FSTYPE", "FATFS", 1);
setenv("CBM_TEST_FSTYPE", "vfat", 1);
autofree(BootManager) *m = NULL;
bootman_select_set_default_vtables();
@@ -119,7 +119,7 @@ END_TEST
START_TEST(bootman_select_uefi_native_without_boot)
{
static PlaygroundConfig config = { "4.2.1-121.kvm", NULL, 0, .uefi = true };
setenv("CBM_TEST_FSTYPE", "FATFS", 1);
setenv("CBM_TEST_FSTYPE", "vfat", 1);
autofree(BootManager) *m = NULL;
bootman_select_set_default_vtables();
@@ -138,7 +138,7 @@ END_TEST
START_TEST(bootman_select_uefi_image_with_boot)
{
static PlaygroundConfig config = { "4.2.1-121.kvm", NULL, 0, .uefi = true };
setenv("CBM_TEST_FSTYPE", "FATFS", 1);
setenv("CBM_TEST_FSTYPE", "vfat", 1);
autofree(BootManager) *m = NULL;
bootman_select_set_default_vtables();
@@ -156,7 +156,7 @@ END_TEST
START_TEST(bootman_select_uefi_image_without_boot)
{
static PlaygroundConfig config = { "4.2.1-121.kvm", NULL, 0, .uefi = true };
setenv("CBM_TEST_FSTYPE", "FATFS", 1);
setenv("CBM_TEST_FSTYPE", "vfat", 1);
autofree(BootManager) *m = NULL;
bootman_select_set_default_vtables();
@@ -240,7 +240,7 @@ static void bootman_select_set_legacy_vtables(void)
START_TEST(bootman_select_extlinux_native_with_boot)
{
PlaygroundConfig config = { "4.2.1-121.kvm", NULL, 0, .uefi = false };
setenv("CBM_TEST_FSTYPE", "EXTFS", 1);
setenv("CBM_TEST_FSTYPE", "ext4", 1);
autofree(BootManager) *m = NULL;
bootman_select_set_legacy_vtables();
@@ -255,7 +255,7 @@ END_TEST
START_TEST(bootman_select_extlinux_image_with_boot)
{
PlaygroundConfig config = { "4.2.1-121.kvm", NULL, 0, .uefi = false };
setenv("CBM_TEST_FSTYPE", "EXTFS", 1);
setenv("CBM_TEST_FSTYPE", "ext4", 1);
autofree(BootManager) *m = NULL;
bootman_select_set_legacy_vtables();
@@ -330,7 +330,7 @@ static void bootman_select_set_grub2_vtables(void)
START_TEST(bootman_select_grub2_native_without_boot)
{
static PlaygroundConfig config = { "4.2.1-121.kvm", NULL, 0, .uefi = false };
setenv("CBM_TEST_FSTYPE", "EXTFS", 1);
setenv("CBM_TEST_FSTYPE", "ext4", 1);
autofree(BootManager) *m = NULL;
bootman_select_set_grub2_vtables();
@@ -355,7 +355,7 @@ END_TEST
START_TEST(bootman_select_edge_uefi_with_legacy_part_native)
{
static PlaygroundConfig config = { "4.2.1-121.kvm", NULL, 0, .uefi = false };
setenv("CBM_TEST_FSTYPE", "EXTFS", 1);
setenv("CBM_TEST_FSTYPE", "ext4", 1);
autofree(BootManager) *m = NULL;
bootman_select_set_legacy_vtables();
@@ -378,7 +378,7 @@ END_TEST
START_TEST(bootman_select_edge_uefi_with_legacy_part_image)
{
static PlaygroundConfig config = { "4.2.1-121.kvm", NULL, 0, .uefi = false };
setenv("CBM_TEST_FSTYPE", "EXTFS", 1);
setenv("CBM_TEST_FSTYPE", "ext4", 1);
autofree(BootManager) *m = NULL;
bootman_select_set_legacy_vtables();
+1 -1
View File
@@ -304,7 +304,7 @@ int main(void)
setenv("CBM_BOOTVAR_TEST_MODE", "yes", 1);
/* Force detection of `ext` filesystem. */
setenv("CBM_TEST_FSTYPE", "EXTFS", 1);
setenv("CBM_TEST_FSTYPE", "ext4", 1);
cbm_blkid_set_vtable(&blkid_ops);
cbm_system_set_vtable(&SystemTestOps);
+1 -1
View File
@@ -638,7 +638,7 @@ int main(void)
setenv("CBM_BOOTVAR_TEST_MODE", "yes", 1);
/* Force detection of `fat` filesystem. */
setenv("CBM_TEST_FSTYPE", "FATFS", 1);
setenv("CBM_TEST_FSTYPE", "vfat", 1);
cbm_blkid_set_vtable(&BlkidTestOps);
cbm_system_set_vtable(&SystemTestOps);