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
21 changes: 20 additions & 1 deletion drivers/disk/Kconfig.ram
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,33 @@ config DISK_RAM_VOLUME_SIZE
int "RAM Disk size in kilobytes"
default 96
help
Size of the RAM Disk.
Size of the RAM Disk. If compression is supported, this
is the maximum size of the uncompressed RAM Disk.

config DISK_RAM_VOLUME_NAME
string "RAM Disk mount point or drive name"
default "RAM"
help
Disk name as per file system naming guidelines.

config DISK_RAM_EXTERNAL
bool "Use initrd provided by the bootloader"
help
Use the initrd provided by the bootloader as the RAM Disk.

config DISK_RAM_START
hex "Start address of the preloaded RAM Disk"
depends on DISK_RAM_EXTERNAL
default 0
help
Start the RAM Disk at a specific address.

config DISK_RAM_DECOMPRESS
bool "Decompress the initrd"
depends on DISK_RAM_EXTERNAL && LZ4
help
Decompress the initrd before using it as the RAM Disk.

module = RAMDISK
module-str = ramdisk
source "subsys/logging/Kconfig.template.log_config"
Expand Down
83 changes: 82 additions & 1 deletion drivers/disk/ramdisk.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,74 @@ LOG_MODULE_REGISTER(ramdisk, CONFIG_RAMDISK_LOG_LEVEL);
#define RAMDISK_VOLUME_SIZE (CONFIG_DISK_RAM_VOLUME_SIZE * 1024)
#define RAMDISK_SECTOR_COUNT (RAMDISK_VOLUME_SIZE / RAMDISK_SECTOR_SIZE)

#if IS_ENABLED(CONFIG_DISK_RAM_DECOMPRESS)
#include <lz4frame.h>
#define LZ4_MAGIC 0x184D2204
static uint8_t unpacked_buf[RAMDISK_VOLUME_SIZE];
#endif

#if IS_ENABLED(CONFIG_DISK_RAM_EXTERNAL)
static uint8_t *ramdisk_buf;
#else
static uint8_t ramdisk_buf[RAMDISK_VOLUME_SIZE];
#endif

#if IS_ENABLED(CONFIG_DISK_RAM_EXTERNAL)
static uint8_t *disk_ram_external_map(void)
{
#if defined(CONFIG_MMU)
uint8_t *virt_start;

z_phys_map(&virt_start, CONFIG_DISK_RAM_START,
RAMDISK_VOLUME_SIZE, K_MEM_CACHE_WB | K_MEM_PERM_RW);
return virt_start;
#else
return (uint8_t *)CONFIG_DISK_RAM_START;
#endif
}
#endif

#if IS_ENABLED(CONFIG_DISK_RAM_DECOMPRESS)
static void disk_ram_external_unmap(char *virt_start)
{
#if defined(CONFIG_MMU)
z_phys_unmap(virt_start, RAMDISK_VOLUME_SIZE);
#endif
}

static int disk_ram_is_compressed(char *virt_start)
{
uint32_t magic = *(uint32_t *)virt_start;

return magic == LZ4_MAGIC;
}

static int disk_ram_decompress(char *compressed_buf, size_t compressed_size,
char *decompressed_buf, size_t decompressed_size)
{
size_t src_size = compressed_size;
size_t dst_size = decompressed_size;
LZ4F_decompressionContext_t lz4_ctx;
int ret;

ret = LZ4F_createDecompressionContext(&lz4_ctx, LZ4F_VERSION);
if (ret < 0) {
LOG_ERR("Can't create decompression context, error: %s\n",
LZ4F_getErrorName(ret));
return ret;
}

ret = LZ4F_decompress(lz4_ctx, decompressed_buf, &dst_size,
compressed_buf, &src_size, NULL);
if (ret < 0) {
LOG_ERR("Decompression failed: %s\n", LZ4F_getErrorName(ret));
return ret;
}
LZ4F_freeDecompressionContext(lz4_ctx);

return ret;
}
#endif

static void *lba_to_address(uint32_t lba)
{
Expand Down Expand Up @@ -105,7 +172,21 @@ static struct disk_info ram_disk = {
static int disk_ram_init(const struct device *dev)
{
ARG_UNUSED(dev);

#if IS_ENABLED(CONFIG_DISK_RAM_EXTERNAL)
ramdisk_buf = disk_ram_external_map();
#if IS_ENABLED(CONFIG_DISK_RAM_DECOMPRESS)
if (disk_ram_is_compressed((char *)ramdisk_buf)) {
if (disk_ram_decompress((char *)ramdisk_buf, RAMDISK_VOLUME_SIZE,
(char *)unpacked_buf, RAMDISK_VOLUME_SIZE) < 0) {
return -EINVAL;
}

LOG_INF("Freeing compressed initrd");
disk_ram_external_unmap(ramdisk_buf);
ramdisk_buf = unpacked_buf;
}
#endif
#endif
return disk_access_register(&ram_disk);
}

Expand Down
2 changes: 2 additions & 0 deletions modules/lz4/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ if(CONFIG_LZ4)

zephyr_library_sources(
${LZ4_DIR}/lib/lz4.c
${LZ4_DIR}/lib/lz4frame.c
${LZ4_DIR}/lib/xxhash.c
)

endif()