From 0f5a467a784d66c93045ccf5b261c137cc306685 Mon Sep 17 00:00:00 2001 From: mintsuki Date: Sat, 2 Jul 2022 10:43:10 +0200 Subject: [PATCH] uri: Add fslabel:// URI scheme as mentioned in #188 --- common/fs/ext2.h | 3 ++- common/fs/ext2.s2.c | 19 +++++++++++++++++++ common/fs/fat32.h | 2 ++ common/fs/fat32.s2.c | 26 ++++++++++++++++++++++++++ common/fs/file.h | 1 + common/fs/file.s2.c | 11 +++++++++++ common/lib/part.h | 3 +++ common/lib/part.s2.c | 35 +++++++++++++++++++++++++++++++++++ common/lib/uri.c | 11 +++++++++++ 9 files changed, 110 insertions(+), 1 deletion(-) diff --git a/common/fs/ext2.h b/common/fs/ext2.h index baedaa77..ad75a5c3 100644 --- a/common/fs/ext2.h +++ b/common/fs/ext2.h @@ -50,7 +50,7 @@ struct ext2_superblock { uint32_t s_feature_ro_compat; uint64_t s_uuid[2]; - uint64_t s_volume_name[2]; + uint8_t s_volume_name[16]; uint64_t s_last_mounted[8]; @@ -124,6 +124,7 @@ struct ext2_file_handle { int ext2_check_signature(struct volume *part); bool ext2_get_guid(struct guid *guid, struct volume *part); +char *ext2_get_label(struct volume *part); bool ext2_open(struct ext2_file_handle *ret, struct volume *part, const char *path); void ext2_read(struct ext2_file_handle *file, void *buf, uint64_t loc, uint64_t count); diff --git a/common/fs/ext2.s2.c b/common/fs/ext2.s2.c index 9e6ddb6a..d1379764 100644 --- a/common/fs/ext2.s2.c +++ b/common/fs/ext2.s2.c @@ -488,3 +488,22 @@ bool ext2_get_guid(struct guid *guid, struct volume *part) { return true; } + +char *ext2_get_label(struct volume *part) { + struct ext2_superblock sb; + volume_read(part, &sb, 1024, sizeof(struct ext2_superblock)); + + if (sb.s_magic != EXT2_S_MAGIC) { + return NULL; + } + + if (sb.s_rev_level < 1) { + return NULL; + } + + size_t label_len = strlen((char *)sb.s_volume_name); + char *ret = ext_mem_alloc(label_len + 1); + strcpy(ret, (char *)sb.s_volume_name); + + return ret; +} diff --git a/common/fs/fat32.h b/common/fs/fat32.h index c2cfd928..052bb2cc 100644 --- a/common/fs/fat32.h +++ b/common/fs/fat32.h @@ -7,6 +7,7 @@ struct fat32_context { struct volume *part; int type; + char label[12]; uint16_t bytes_per_sector; uint8_t sectors_per_cluster; uint16_t reserved_sectors; @@ -31,6 +32,7 @@ struct fat32_file_handle { }; int fat32_check_signature(struct volume *part); +char *fat32_get_label(struct volume *part); bool fat32_open(struct fat32_file_handle *ret, struct volume *part, const char *path); void fat32_read(struct fat32_file_handle *file, void *buf, uint64_t loc, uint64_t count); diff --git a/common/fs/fat32.s2.c b/common/fs/fat32.s2.c index 38255046..1f75ff91 100644 --- a/common/fs/fat32.s2.c +++ b/common/fs/fat32.s2.c @@ -124,6 +124,15 @@ valid:; context->type = 32; } + memcpy(context->label, bpb.label, 11); + context->label[11] = 0; + // remove trailing spaces + for (int i = 10; i >= 0; i--) { + if (context->label[i] == ' ') { + context->label[i] = 0; + } + } + context->bytes_per_sector = bpb.bytes_per_sector; context->sectors_per_cluster = bpb.sectors_per_cluster; context->reserved_sectors = bpb.reserved_sectors; @@ -362,6 +371,23 @@ int fat32_check_signature(struct volume *part) { return fat32_init_context(&context, part) == 0; } +char *fat32_get_label(struct volume *part) { + struct fat32_context context; + if (fat32_init_context(&context, part) != 0) { + return NULL; + } + + size_t label_len = strlen(context.label); + if (label_len == 0) { + return NULL; + } + + char *ret = ext_mem_alloc(label_len + 1); + strcpy(ret, context.label); + + return ret; +} + bool fat32_open(struct fat32_file_handle* ret, struct volume *part, const char* path) { struct fat32_context context; int r = fat32_init_context(&context, part); diff --git a/common/fs/file.h b/common/fs/file.h index a464c34e..62602171 100644 --- a/common/fs/file.h +++ b/common/fs/file.h @@ -12,6 +12,7 @@ #define PATH_MAX 4096 bool fs_get_guid(struct guid *guid, struct volume *part); +char *fs_get_label(struct volume *part); struct file_handle { bool is_memfile; diff --git a/common/fs/file.s2.c b/common/fs/file.s2.c index 5eedb623..fe9ed8fc 100644 --- a/common/fs/file.s2.c +++ b/common/fs/file.s2.c @@ -12,6 +12,17 @@ #include #include +char *fs_get_label(struct volume *part) { + if (fat32_check_signature(part)) { + return fat32_get_label(part); + } + if (ext2_check_signature(part)) { + return ext2_get_label(part); + } + + return NULL; +} + bool fs_get_guid(struct guid *guid, struct volume *part) { if (ext2_check_signature(part)) { return ext2_get_guid(guid, part); diff --git a/common/lib/part.h b/common/lib/part.h index f468b7d8..9de453f5 100644 --- a/common/lib/part.h +++ b/common/lib/part.h @@ -50,6 +50,8 @@ struct volume { struct guid guid; bool part_guid_valid; struct guid part_guid; + bool fslabel_valid; + char *fslabel; }; void list_volumes(void); @@ -63,6 +65,7 @@ uint32_t mbr_get_id(struct volume *volume); int part_get(struct volume *part, struct volume *volume, int partition); struct volume *volume_get_by_guid(struct guid *guid); +struct volume *volume_get_by_fslabel(char *fslabel); struct volume *volume_get_by_coord(bool optical, int drive, int partition); #if bios == 1 struct volume *volume_get_by_bios_drive(int drive); diff --git a/common/lib/part.s2.c b/common/lib/part.s2.c index 2bceb998..7abd51ee 100644 --- a/common/lib/part.s2.c +++ b/common/lib/part.s2.c @@ -221,6 +221,14 @@ static int gpt_get_part(struct volume *ret, struct volume *volume, int partition ret->guid = guid; } + char *fslabel = fs_get_label(ret); + if (fslabel == NULL) { + ret->fslabel_valid = false; + } else { + ret->fslabel_valid = true; + ret->fslabel = fslabel; + } + ret->part_guid_valid = true; ret->part_guid = entry.unique_partition_guid; @@ -339,6 +347,14 @@ static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part ret->guid = guid; } + char *fslabel = fs_get_label(ret); + if (fslabel == NULL) { + ret->fslabel_valid = false; + } else { + ret->fslabel_valid = true; + ret->fslabel = fslabel; + } + ret->part_guid_valid = false; return 0; @@ -413,6 +429,14 @@ static int mbr_get_part(struct volume *ret, struct volume *volume, int partition ret->guid = guid; } + char *fslabel = fs_get_label(ret); + if (fslabel == NULL) { + ret->fslabel_valid = false; + } else { + ret->fslabel_valid = true; + ret->fslabel = fslabel; + } + ret->part_guid_valid = false; return 0; @@ -450,6 +474,17 @@ struct volume *volume_get_by_guid(struct guid *guid) { return NULL; } +struct volume *volume_get_by_fslabel(char *fslabel) { + for (size_t i = 0; i < volume_index_i; i++) { + if (volume_index[i]->fslabel_valid + && strcmp(volume_index[i]->fslabel, fslabel) == 0) { + return volume_index[i]; + } + } + + return NULL; +} + struct volume *volume_get_by_coord(bool optical, int drive, int partition) { for (size_t i = 0; i < volume_index_i; i++) { if (volume_index[i]->index == drive diff --git a/common/lib/uri.c b/common/lib/uri.c index 055d71d3..3f677224 100644 --- a/common/lib/uri.c +++ b/common/lib/uri.c @@ -133,6 +133,15 @@ static struct file_handle *uri_guid_dispatch(char *guid_str, char *path) { return fopen(volume, path); } +static struct file_handle *uri_fslabel_dispatch(char *fslabel, char *path) { + struct volume *volume = volume_get_by_fslabel(fslabel); + if (volume == NULL) { + return NULL; + } + + return fopen(volume, path); +} + static struct file_handle *uri_fwcfg_dispatch(char *path) { struct file_handle *ret = ext_mem_alloc(sizeof(struct file_handle)); if (!fwcfg_open(ret, path)) { @@ -216,6 +225,8 @@ struct file_handle *uri_open(char *uri) { ret = uri_guid_dispatch(root, path); } else if (!strcmp(resource, "uuid")) { ret = uri_guid_dispatch(root, path); + } else if (!strcmp(resource, "fslabel")) { + ret = uri_fslabel_dispatch(root, path); #if bios == 1 } else if (!strcmp(resource, "tftp")) { ret = uri_tftp_dispatch(root, path);