diff --git a/diskmngr/Makefile b/diskmngr/Makefile new file mode 100644 index 000000000..c423627fe --- /dev/null +++ b/diskmngr/Makefile @@ -0,0 +1,30 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=diskmngr +PKG_VERSION:=1.0.0 +PKG_RELEASE:=1 + +PKG_LICENSE:=GPL-2.0-only + +include $(INCLUDE_DIR)/package.mk +include ../bbfdm/bbfdm.mk + +define Package/diskmngr + CATEGORY:=Utilities + TITLE:=Storage Info + DEPENDS+=+libbbfdm-api +libbbfdm-ubus +dm-service + MENU:=1 +endef + +define Package/diskmngr/description + Provides TR181 datamodel for Storage devices +endef + +TARGET_CFLAGS += -DBBF_VENDOR_PREFIX=\\\"$(CONFIG_BBF_VENDOR_PREFIX)\\\" + +define Package/diskmngr/install + $(BBFDM_REGISTER_SERVICES) -v ${CONFIG_BBF_VENDOR_PREFIX} ./bbfdm_service.json $(1) $(PKG_NAME) + $(BBFDM_INSTALL_MS_DM) $(PKG_BUILD_DIR)/libdiskmngr.so $(1) $(PKG_NAME) +endef + +$(eval $(call BuildPackage,diskmngr)) diff --git a/diskmngr/bbfdm_service.json b/diskmngr/bbfdm_service.json new file mode 100644 index 000000000..9563c87b9 --- /dev/null +++ b/diskmngr/bbfdm_service.json @@ -0,0 +1,16 @@ +{ + "daemon": { + "enable": "1", + "service_name": "diskmngr", + "unified_daemon": false, + "services": [ + { + "parent_dm": "Device.", + "object": "{BBF_VENDOR_PREFIX}Storage" + } + ], + "config": { + "loglevel": "3" + } + } +} diff --git a/diskmngr/src/LICENSE b/diskmngr/src/LICENSE new file mode 100644 index 000000000..a1d1c2850 --- /dev/null +++ b/diskmngr/src/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2023-2026, IOPSYS +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/diskmngr/src/Makefile b/diskmngr/src/Makefile new file mode 100644 index 000000000..9ed7c69e8 --- /dev/null +++ b/diskmngr/src/Makefile @@ -0,0 +1,21 @@ +LIBOUT := libdiskmngr.so + +LIBOBJS := disk.o + +PROG_CFLAGS = $(CFLAGS) -Wall -Werror -fstrict-aliasing -g +LIB_LDFLAGS = $(LDFLAGS) + +FPIC := -fPIC + +.PHONY: all + +%.o: %.c + $(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $< + +all: $(LIBOUT) + +$(LIBOUT): $(LIBOBJS) + $(CC) $(PROG_CFLAGS) $(LIB_LDFLAGS) -shared -o $@ $^ + +clean: + rm -f *.o $(LIBOUT) diff --git a/diskmngr/src/disk.c b/diskmngr/src/disk.c new file mode 100644 index 000000000..96053b7ed --- /dev/null +++ b/diskmngr/src/disk.c @@ -0,0 +1,705 @@ +/* + * Copyright (C) 2025 Genexis Sweden AB + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + */ + +#include +#include +#include +#include +#include + +typedef struct mount_entry { + struct list_head list; + char device[256]; + char mount_point[256]; + char fs_type[64]; +} mount_entry; + +typedef struct partition_entry { + struct list_head list; + char device[256]; /* e.g., /dev/mmcblk0p4 */ + char mount_point[256]; /* "" if not mounted */ + char fs_type[64]; /* "" if not mounted */ + int partition_number; + bool is_mounted; + /* Space stats cached at enumerate time; 0 if not mounted */ + unsigned long long capacity; + unsigned long long used; + unsigned long long available; +} partition_entry; + +typedef struct physical_disk_entry { + struct list_head list; + struct list_head partitions; + char device[256]; /* e.g., /dev/mmcblk0 */ + char model[256]; + unsigned long long size; /* bytes */ + int partition_count; +} physical_disk_entry; + +static LIST_HEAD(storage_list); +static LIST_HEAD(mount_table); + +/************************************************************* + * SYSFS HELPERS + *************************************************************/ +static unsigned long long read_sysfs_ull(const char *path) +{ + FILE *fp; + unsigned long long val = 0; + + fp = fopen(path, "r"); + if (fp) { + fscanf(fp, "%llu", &val); + fclose(fp); + } + return val; +} + +static void read_sysfs_str(const char *path, char *buf, size_t len) +{ + FILE *fp; + char *p; + + buf[0] = '\0'; + fp = fopen(path, "r"); + if (!fp) + return; + if (fgets(buf, len, fp)) { + p = buf + strlen(buf) - 1; + while (p >= buf && (*p == '\n' || *p == '\r' || *p == ' ')) + *p-- = '\0'; + } + fclose(fp); +} + +static void get_disk_model(const char *disk_name, char *model, size_t model_size) +{ + char path[256]; + + snprintf(path, sizeof(path), "/sys/block/%s/device/model", disk_name); + read_sysfs_str(path, model, model_size); + if (model[0]) + return; + + snprintf(path, sizeof(path), "/sys/block/%s/device/name", disk_name); + read_sysfs_str(path, model, model_size); + if (model[0]) + return; + + snprintf(model, model_size, "Unknown"); +} + +/************************************************************* + * STATVFS HELPER + *************************************************************/ +static int get_disk_stats(const char *mount_point, unsigned long long *capacity, + unsigned long long *used, unsigned long long *available) +{ + struct statvfs s; + unsigned long long blksize; + + if (statvfs(mount_point, &s) != 0) + return -1; + + blksize = s.f_frsize ? s.f_frsize : s.f_bsize; + *capacity = s.f_blocks * blksize; + *used = (s.f_blocks - s.f_bfree) * blksize; + *available = s.f_bavail * blksize; + return 0; +} + +/************************************************************* + * MOUNT TABLE + *************************************************************/ +static void free_mount_table(void) +{ + mount_entry *e, *tmp; + + list_for_each_entry_safe(e, tmp, &mount_table, list) { + list_del(&e->list); + BBFDM_FREE(e); + } +} + +static void load_mount_table(void) +{ + FILE *fp; + char line[512]; + + free_mount_table(); + + fp = fopen("/proc/mounts", "r"); + if (!fp) + return; + + while (fgets(line, sizeof(line), fp)) { + char device[256] = {0}, mount_point[256] = {0}, fs_type[64] = {0}; + mount_entry *e; + + if (sscanf(line, "%255s %255s %63s", device, mount_point, fs_type) != 3) + continue; + /* Accept block devices under /dev/ and UBI volumes (ubiN:volname) */ + if (strncmp(device, "/dev/", 5) != 0 && + !(strncmp(device, "ubi", 3) == 0 && strchr(device, ':') != NULL)) + continue; + + e = calloc(1, sizeof(mount_entry)); + if (!e) { + syslog(LOG_ERR, "Storage: Failed to allocate memory for mount entry"); + continue; + } + + strncpy(e->device, device, sizeof(e->device) - 1); + strncpy(e->mount_point, mount_point, sizeof(e->mount_point) - 1); + strncpy(e->fs_type, fs_type, sizeof(e->fs_type) - 1); + list_add_tail(&e->list, &mount_table); + } + fclose(fp); +} + +static mount_entry *find_mount(const char *device) +{ + mount_entry *e; + + list_for_each_entry(e, &mount_table, list) { + if (strcmp(e->device, device) == 0) + return e; + } + return NULL; +} + +/************************************************************* + * STORAGE LIST MANAGEMENT + *************************************************************/ +static void free_storage_list(void) +{ + physical_disk_entry *disk, *disk_tmp; + partition_entry *part, *part_tmp; + + list_for_each_entry_safe(disk, disk_tmp, &storage_list, list) { + list_for_each_entry_safe(part, part_tmp, &disk->partitions, list) { + list_del(&part->list); + BBFDM_FREE(part); + } + list_del(&disk->list); + BBFDM_FREE(disk); + } +} + +static bool is_physical_disk(const char *name) +{ + const char *p; + + if (strncmp(name, "mmcblk", 6) == 0) { + /* Accept only mmcblkN — reject mmcblkNboot0, mmcblkNrpmb, etc. */ + p = name + 6; + while (*p && isdigit_str(p)) + p++; + return *p == '\0'; + } + + return strncmp(name, "sd", 2) == 0 || + strncmp(name, "hd", 2) == 0 || + strncmp(name, "vd", 2) == 0 || + strncmp(name, "nvme", 4) == 0; +} + +static void enumerate_ubi_devices(void) +{ + DIR *ubi_dir; + struct dirent *de; + struct dirent **entries = NULL; + int n_entries = 0, i; + char path[256]; + + ubi_dir = opendir("/sys/class/ubi"); + if (!ubi_dir) + return; /* No UBI support on this system */ + + /* Collect all directory entries first */ + while ((de = readdir(ubi_dir)) != NULL) { + struct dirent **tmp = realloc(entries, (n_entries + 1) * sizeof(struct dirent *)); + if (!tmp) { + syslog(LOG_ERR, "Storage: Failed to allocate memory for UBI entries"); + goto cleanup; + } + entries = tmp; + entries[n_entries] = malloc(sizeof(struct dirent)); + if (!entries[n_entries]) { + syslog(LOG_ERR, "Storage: Failed to allocate memory for UBI entry"); + goto cleanup; + } + memcpy(entries[n_entries], de, sizeof(struct dirent)); + n_entries++; + } + closedir(ubi_dir); + + /* Process UBI devices */ + for (i = 0; i < n_entries; i++) { + const char *ubi_name = entries[i]->d_name; + const char *p; + physical_disk_entry *disk; + unsigned long long total_lebs, leb_size; + char vol_prefix[32]; + int j; + + /* Match ubiN only (not ubiN_M volume entries) */ + if (strncmp(ubi_name, "ubi", 3) != 0) + continue; + p = ubi_name + 3; + if (!*p || !isdigit((unsigned char)*p)) + continue; + while (*p && isdigit((unsigned char)*p)) + p++; + if (*p != '\0') + continue; + + disk = calloc(1, sizeof(physical_disk_entry)); + if (!disk) { + syslog(LOG_ERR, "Storage: Failed to allocate memory for UBI disk %s", ubi_name); + continue; + } + + INIT_LIST_HEAD(&disk->partitions); + snprintf(disk->device, sizeof(disk->device), "/dev/%s", ubi_name); + snprintf(disk->model, sizeof(disk->model), "NAND Flash (UBI)"); + + snprintf(path, sizeof(path), "/sys/class/ubi/%s/total_eraseblocks", ubi_name); + total_lebs = read_sysfs_ull(path); + snprintf(path, sizeof(path), "/sys/class/ubi/%s/eraseblock_size", ubi_name); + leb_size = read_sysfs_ull(path); + disk->size = total_lebs * leb_size; + + /* Enumerate volumes: ubiN_M entries */ + snprintf(vol_prefix, sizeof(vol_prefix), "%s_", ubi_name); + for (j = 0; j < n_entries; j++) { + const char *vol_entry = entries[j]->d_name; + char vol_name[128] = {0}; + char ubi_dev[256]; + partition_entry *part; + mount_entry *mnt; + unsigned long long usable_leb, reserved_ebs; + + if (strncmp(vol_entry, vol_prefix, strlen(vol_prefix)) != 0) + continue; + + part = calloc(1, sizeof(partition_entry)); + if (!part) { + syslog(LOG_ERR, "Storage: Failed to allocate memory for UBI volume %s", vol_entry); + continue; + } + + /* Volume ID from the suffix after "ubiN_" */ + part->partition_number = atoi(vol_entry + strlen(vol_prefix)); + + /* Volume name from sysfs (e.g., "boarddata") */ + snprintf(path, sizeof(path), "/sys/class/ubi/%s/name", vol_entry); + read_sysfs_str(path, vol_name, sizeof(vol_name)); + + /* Ensure volume name is valid to prevent buffer issues */ + if (vol_name[0] == '\0') { + syslog(LOG_WARNING, "Storage: Empty volume name for %s", vol_entry); + BBFDM_FREE(part); + continue; + } + + /* Device name as "ubiN:volname" — matches /proc/mounts */ + snprintf(ubi_dev, sizeof(ubi_dev), "%s:%s", ubi_name, vol_name); + snprintf(part->device, sizeof(part->device), "%s", ubi_dev); + + /* Capacity from sysfs */ + snprintf(path, sizeof(path), "/sys/class/ubi/%s/usable_leb_size", vol_entry); + usable_leb = read_sysfs_ull(path); + snprintf(path, sizeof(path), "/sys/class/ubi/%s/reserved_ebs", vol_entry); + reserved_ebs = read_sysfs_ull(path); + part->capacity = usable_leb * reserved_ebs; + + mnt = find_mount(ubi_dev); + if (mnt) { + part->is_mounted = true; + strncpy(part->mount_point, mnt->mount_point, + sizeof(part->mount_point) - 1); + strncpy(part->fs_type, mnt->fs_type, + sizeof(part->fs_type) - 1); + /* Override with live statvfs where available */ + get_disk_stats(part->mount_point, &part->capacity, + &part->used, &part->available); + } else { + /* For static volumes, data_bytes reflects actual content */ + snprintf(path, sizeof(path), "/sys/class/ubi/%s/data_bytes", vol_entry); + part->used = read_sysfs_ull(path); + } + + list_add_tail(&part->list, &disk->partitions); + disk->partition_count++; + } + + list_add_tail(&disk->list, &storage_list); + syslog(LOG_DEBUG, "Storage: ubi=%s size=%llu volumes=%d", + disk->device, disk->size, disk->partition_count); + } + +cleanup: + for (i = 0; i < n_entries; i++) + free(entries[i]); + free(entries); +} + +static void enumerate_storage(void) +{ + DIR *block_dir, *disk_dir; + struct dirent *disk_de, *part_de; + char path[256]; + + free_storage_list(); + load_mount_table(); + + block_dir = opendir("/sys/block"); + if (!block_dir) { + syslog(LOG_ERR, "Storage: Failed to open /sys/block"); + return; + } + + while ((disk_de = readdir(block_dir)) != NULL) { + const char *disk_name = disk_de->d_name; + physical_disk_entry *disk; + + if (!is_physical_disk(disk_name)) + continue; + + disk = calloc(1, sizeof(physical_disk_entry)); + if (!disk) { + syslog(LOG_ERR, "Storage: Failed to allocate memory for disk %s", disk_name); + continue; + } + + INIT_LIST_HEAD(&disk->partitions); + snprintf(disk->device, sizeof(disk->device), "/dev/%s", disk_name); + + snprintf(path, sizeof(path), "/sys/block/%s/size", disk_name); + disk->size = read_sysfs_ull(path) * 512; + + get_disk_model(disk_name, disk->model, sizeof(disk->model)); + + /* Walk /sys/block// for partitions (identified by 'partition' file) */ + snprintf(path, sizeof(path), "/sys/block/%s", disk_name); + disk_dir = opendir(path); + if (disk_dir) { + while ((part_de = readdir(disk_dir)) != NULL) { + const char *part_name = part_de->d_name; + char part_sysfs[256]; + partition_entry *part; + mount_entry *mnt; + + /* Partitions start with the disk name */ + if (strncmp(part_name, disk_name, strlen(disk_name)) != 0) + continue; + + /* Confirm it is a partition via the sysfs 'partition' file */ + snprintf(part_sysfs, sizeof(part_sysfs), + "/sys/block/%s/%s/partition", disk_name, part_name); + if (!bbfdm_file_exists(part_sysfs)) + continue; + + part = calloc(1, sizeof(partition_entry)); + if (!part) { + syslog(LOG_ERR, "Storage: Failed to allocate memory for partition %s", part_name); + continue; + } + + snprintf(part->device, sizeof(part->device), "/dev/%s", part_name); + part->partition_number = (int)read_sysfs_ull(part_sysfs); + + mnt = find_mount(part->device); + if (mnt) { + part->is_mounted = true; + strncpy(part->mount_point, mnt->mount_point, + sizeof(part->mount_point) - 1); + strncpy(part->fs_type, mnt->fs_type, + sizeof(part->fs_type) - 1); + get_disk_stats(part->mount_point, &part->capacity, + &part->used, &part->available); + } else { + snprintf(part_sysfs, sizeof(part_sysfs), + "/sys/block/%s/%s/size", disk_name, part_name); + part->capacity = read_sysfs_ull(part_sysfs) * 512; + } + + list_add_tail(&part->list, &disk->partitions); + disk->partition_count++; + } + closedir(disk_dir); + } + + list_add_tail(&disk->list, &storage_list); + syslog(LOG_DEBUG, "Storage: disk=%s model=%s size=%llu partitions=%d", + disk->device, disk->model, disk->size, disk->partition_count); + } + + closedir(block_dir); + + enumerate_ubi_devices(); + + free_mount_table(); +} + +/************************************************************* + * GET PARAMS - Storage.{i}. + *************************************************************/ +static int get_storage_name(char *refparam, struct dmctx *ctx, void *data, + char *instance, char **value) +{ + physical_disk_entry *e = (physical_disk_entry *)((struct dm_data *)data)->additional_data; + *value = e ? dmstrdup(e->device) : dmstrdup(""); + return 0; +} + +static int get_storage_model(char *refparam, struct dmctx *ctx, void *data, + char *instance, char **value) +{ + physical_disk_entry *e = (physical_disk_entry *)((struct dm_data *)data)->additional_data; + *value = e ? dmstrdup(e->model) : dmstrdup("Unknown"); + return 0; +} + +static int get_storage_capacity(char *refparam, struct dmctx *ctx, void *data, + char *instance, char **value) +{ + physical_disk_entry *e = (physical_disk_entry *)((struct dm_data *)data)->additional_data; + dmasprintf(value, "%llu", e ? e->size : 0ULL); + return 0; +} + +static int get_storage_status(char *refparam, struct dmctx *ctx, void *data, + char *instance, char **value) +{ + physical_disk_entry *e = (physical_disk_entry *)((struct dm_data *)data)->additional_data; + *value = (e && e->size > 0) ? dmstrdup("Online") : dmstrdup("Offline"); + return 0; +} + +static int get_storage_partition_number_of_entries(char *refparam, struct dmctx *ctx, + void *data, char *instance, char **value) +{ + physical_disk_entry *e = (physical_disk_entry *)((struct dm_data *)data)->additional_data; + dmasprintf(value, "%d", e ? e->partition_count : 0); + return 0; +} + +/************************************************************* + * GET PARAMS - Storage.{i}.Partition.{i}. + *************************************************************/ +static int get_partition_name(char *refparam, struct dmctx *ctx, void *data, + char *instance, char **value) +{ + partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data; + *value = e ? dmstrdup(e->device) : dmstrdup(""); + return 0; +} + +static int get_partition_number(char *refparam, struct dmctx *ctx, void *data, + char *instance, char **value) +{ + partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data; + dmasprintf(value, "%d", e ? e->partition_number : 0); + return 0; +} + +static int get_partition_filesystem(char *refparam, struct dmctx *ctx, void *data, + char *instance, char **value) +{ + partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data; + *value = e ? dmstrdup(e->fs_type) : dmstrdup(""); + return 0; +} + +static int get_partition_mount_point(char *refparam, struct dmctx *ctx, void *data, + char *instance, char **value) +{ + partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data; + *value = e ? dmstrdup(e->mount_point) : dmstrdup(""); + return 0; +} + +static int get_partition_status(char *refparam, struct dmctx *ctx, void *data, + char *instance, char **value) +{ + partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data; + *value = (e && e->is_mounted) ? dmstrdup("Mounted") : dmstrdup("Unmounted"); + return 0; +} + +static int get_partition_capacity(char *refparam, struct dmctx *ctx, void *data, + char *instance, char **value) +{ + partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data; + dmasprintf(value, "%llu", e ? e->capacity : 0ULL); + return 0; +} + +static int get_partition_used_space(char *refparam, struct dmctx *ctx, void *data, + char *instance, char **value) +{ + partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data; + dmasprintf(value, "%llu", e ? e->used : 0ULL); + return 0; +} + +static int get_partition_available_space(char *refparam, struct dmctx *ctx, void *data, + char *instance, char **value) +{ + partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data; + dmasprintf(value, "%llu", e ? e->available : 0ULL); + return 0; +} + +static int get_partition_used_percentage(char *refparam, struct dmctx *ctx, void *data, + char *instance, char **value) +{ + partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data; + unsigned int pct = 0; + + if (e && e->capacity > 0) + pct = (unsigned int)((e->used * 100) / e->capacity); + dmasprintf(value, "%u", pct); + return 0; +} + +/************************************************************* + * NUMBER OF ENTRIES + *************************************************************/ +static int get_storage_number_of_entries(char *refparam, struct dmctx *ctx, void *data, + char *instance, char **value) +{ + physical_disk_entry *e; + int count = 0; + + enumerate_storage(); + list_for_each_entry(e, &storage_list, list) + count++; + dmasprintf(value, "%d", count); + return 0; +} + +/************************************************************* + * BROWSE + *************************************************************/ +static int browseStorageInst(struct dmctx *dmctx, DMNODE *parent_node, + void *prev_data, char *prev_instance) +{ + physical_disk_entry *e; + struct dm_data curr_data = {0}; + char *inst; + int id = 0; + + enumerate_storage(); + + list_for_each_entry(e, &storage_list, list) { + curr_data.additional_data = e; + inst = handle_instance_without_section(dmctx, parent_node, ++id); + if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP) + break; + } + return 0; +} + +static int browsePartitionInst(struct dmctx *dmctx, DMNODE *parent_node, + void *prev_data, char *prev_instance) +{ + physical_disk_entry *disk = (physical_disk_entry *)((struct dm_data *)prev_data)->additional_data; + partition_entry *e; + struct dm_data curr_data = {0}; + char *inst; + int id = 0; + + if (!disk) + return 0; + + list_for_each_entry(e, &disk->partitions, list) { + curr_data.additional_data = e; + inst = handle_instance_without_section(dmctx, parent_node, ++id); + if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP) + break; + } + return 0; +} + +/************************************************************* + * INIT / CLEAN + *************************************************************/ +void sysmngr_disk_init(void) +{ + enumerate_storage(); +} + +void sysmngr_disk_clean(void) +{ + free_storage_list(); +} + +/********************************************************************************************************************************** +* OBJ & LEAF DEFINITION +***********************************************************************************************************************************/ + +/* *** Device.DeviceInfo.X_*_Storage.{i}.Partition.{i}. *** */ +DMLEAF tDeviceInfoStoragePartitionParams[] = { +/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */ +{"Name", &DMREAD, DMT_STRING, get_partition_name, NULL, BBFDM_BOTH}, +{"PartitionNumber", &DMREAD, DMT_UNINT, get_partition_number, NULL, BBFDM_BOTH}, +{"FileSystem", &DMREAD, DMT_STRING, get_partition_filesystem, NULL, BBFDM_BOTH}, +{"MountPoint", &DMREAD, DMT_STRING, get_partition_mount_point, NULL, BBFDM_BOTH}, +{"Status", &DMREAD, DMT_STRING, get_partition_status, NULL, BBFDM_BOTH}, +{"Capacity", &DMREAD, DMT_UNLONG, get_partition_capacity, NULL, BBFDM_BOTH}, +{"UsedSpace", &DMREAD, DMT_UNLONG, get_partition_used_space, NULL, BBFDM_BOTH}, +{"AvailableSpace", &DMREAD, DMT_UNLONG, get_partition_available_space, NULL, BBFDM_BOTH}, +{"UsedPercentage", &DMREAD, DMT_UNINT, get_partition_used_percentage, NULL, BBFDM_BOTH}, +{0} +}; + +/* *** Device.DeviceInfo.X_*_Storage.{i}. *** */ +DMOBJ tDeviceInfoStorageInstanceObj[] = { +/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type */ +{"Partition", &DMREAD, NULL, NULL, NULL, browsePartitionInst, NULL, NULL, NULL, tDeviceInfoStoragePartitionParams, NULL, BBFDM_BOTH}, +{0} +}; + +DMLEAF tDeviceInfoStorageInstanceParams[] = { +/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */ +{"Name", &DMREAD, DMT_STRING, get_storage_name, NULL, BBFDM_BOTH}, +{"Model", &DMREAD, DMT_STRING, get_storage_model, NULL, BBFDM_BOTH}, +{"Capacity", &DMREAD, DMT_UNLONG, get_storage_capacity, NULL, BBFDM_BOTH}, +{"Status", &DMREAD, DMT_STRING, get_storage_status, NULL, BBFDM_BOTH}, +{"PartitionNumberOfEntries", &DMREAD, DMT_UNINT, get_storage_partition_number_of_entries, NULL, BBFDM_BOTH}, +{0} +}; + +/* *** Device.DeviceInfo.X_*_Storage. *** */ +DMOBJ tDeviceInfoStorageObj[] = { +/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type */ +{"Storage", &DMREAD, NULL, NULL, NULL, browseStorageInst, NULL, NULL, tDeviceInfoStorageInstanceObj, tDeviceInfoStorageInstanceParams, NULL, BBFDM_BOTH}, +{0} +}; + +DMLEAF tDeviceInfoStorageParams[] = { +/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */ +{"StorageNumberOfEntries", &DMREAD, DMT_UNINT, get_storage_number_of_entries, NULL, BBFDM_BOTH}, +{0} +}; + +DMOBJ tDeviceStorageObj[] = { +/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type */ +{BBF_VENDOR_PREFIX"Storage", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceInfoStorageObj, tDeviceInfoStorageParams, NULL, BBFDM_BOTH}, +{0} +}; + +DM_MAP_OBJ tDynamicObj[] = { +/* parentobj, nextobject, parameter */ +{"Device.", tDeviceStorageObj, NULL}, +{0} +}; diff --git a/diskmngr/src/disk.h b/diskmngr/src/disk.h new file mode 100644 index 000000000..46323db07 --- /dev/null +++ b/diskmngr/src/disk.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2025 Genexis Sweden AB + */ + +#ifndef __DISK_H +#define __DISK_H + +extern DMOBJ tDeviceInfoStorageObj[]; +extern DMLEAF tDeviceInfoStorageParams[]; + +void sysmngr_disk_init(void); +void sysmngr_disk_clean(void); + +#endif //__DISK_H