luckfox-pico-sdk/sysdrv/source/mcu/rt-thread/tools/mklfs/mklfs.c
luckfox-eng29 8f34c2760d project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.
project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between
the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door
for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more
usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp:
Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for
compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem.
sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device
tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately.
sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick
boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades.
sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for
fastboot.

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
2024-10-14 09:47:04 +08:00

308 lines
7.8 KiB
C

/*
* Copyright (C) 2015 - 2018, IBEROXARXA SERVICIOS INTEGRALES, S.L.
* Copyright (C) 2015 - 2018, Jaume Olivé Petrus (jolive@whitecatboard.org)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
* * The WHITECAT logotype cannot be changed, you can remove it, but you
* cannot change it in any way. The WHITECAT logotype is:
*
* /\ /\
* / \_____/ \
* /_____________\
* W H I T E C A T
*
* * Redistributions in binary form must retain all copyright notices printed
* to any local or remote output device. This include any reference to
* Lua RTOS, whitecatboard.org, Lua, and other copyright notices that may
* appear in the future.
*
* 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 <COPYRIGHT HOLDER> 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.
*
* Lua RTOS, a tool for make a LFS file system image
*
*/
#include "lfs/lfs.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <dirent.h>
#include <sys/types.h>
static struct lfs_config cfg;
static lfs_t lfs;
static uint8_t *data;
static int lfs_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) {
memcpy(buffer, data + (block * c->block_size) + off, size);
return 0;
}
static int lfs_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) {
memcpy(data + (block * c->block_size) + off, buffer, size);
return 0;
}
static int lfs_erase(const struct lfs_config *c, lfs_block_t block) {
memset(data + (block * c->block_size), 0, c->block_size);
return 0;
}
static int lfs_sync(const struct lfs_config *c) {
return 0;
}
static void create_dir(char *src) {
char *path;
int ret;
path = strchr(src, '/');
if (path) {
fprintf(stdout, "%s\r\n", path);
if ((ret = lfs_mkdir(&lfs, path)) < 0) {
fprintf(stderr,"can't create directory %s: error=%d\r\n", path, ret);
exit(1);
}
}
}
static void create_file(char *src) {
char *path;
int ret;
path = strchr(src, '/');
if (path) {
fprintf(stdout, "%s\r\n", path);
// Open source file
FILE *srcf = fopen(src,"rb");
if (!srcf) {
fprintf(stderr,"can't open source file %s: errno=%d (%s)\r\n", src, errno, strerror(errno));
exit(1);
}
// Open destination file
lfs_file_t dstf;
if ((ret = lfs_file_open(&lfs, &dstf, path, LFS_O_WRONLY | LFS_O_CREAT)) < 0) {
fprintf(stderr,"can't open destination file %s: error=%d\r\n", path, ret);
exit(1);
}
char c = fgetc(srcf);
while (!feof(srcf)) {
ret = lfs_file_write(&lfs, &dstf, &c, 1);
if (ret < 0) {
fprintf(stderr,"can't write to destination file %s: error=%d\r\n", path, ret);
exit(1);
}
c = fgetc(srcf);
}
// Close destination file
ret = lfs_file_close(&lfs, &dstf);
if (ret < 0) {
fprintf(stderr,"can't close destination file %s: error=%d\r\n", path, ret);
exit(1);
}
// Close source file
fclose(srcf);
}
}
static void compact(char *src) {
DIR *dir;
struct dirent *ent;
char curr_path[PATH_MAX];
dir = opendir(src);
if (dir) {
while ((ent = readdir(dir))) {
// Skip . and .. directories
if ((strcmp(ent->d_name,".") != 0) && (strcmp(ent->d_name,"..") != 0)) {
// Update the current path
strcpy(curr_path, src);
strcat(curr_path, "/");
strcat(curr_path, ent->d_name);
if (ent->d_type == DT_DIR) {
create_dir(curr_path);
compact(curr_path);
} else if (ent->d_type == DT_REG) {
create_file(curr_path);
}
}
}
closedir(dir);
}
}
void usage() {
fprintf(stdout, "usage: mklfs -c <pack-dir> -b <block-size> -r <read-size> -p <prog-size> -s <filesystem-size> -i <image-file-path>\r\n");
}
static int is_number(const char *s) {
const char *c = s;
while (*c) {
if ((*c < '0') || (*c > '9')) {
return 0;
}
c++;
}
return 1;
}
static int is_hex(const char *s) {
const char *c = s;
if (*c++ != '0') {
return 0;
}
if (*c++ != 'x') {
return 0;
}
while (*c) {
if (((*c < '0') || (*c > '9')) && ((*c < 'A') || (*c > 'F')) && ((*c < 'a') || (*c > 'f'))) {
return 0;
}
c++;
}
return 1;
}
static int to_int(const char *s) {
if (is_number(s)) {
return atoi(s);
} else if (is_hex(s)) {
return (int)strtol(s, NULL, 16);
}
return -1;
}
int main(int argc, char **argv) {
char *src = NULL; // Source directory
char *dst = NULL; // Destination image
int c; // Current option
int block_size = 0; // Block size
int read_size = 0; // Read size
int prog_size = 0; // Prog size
int fs_size = 0; // File system size
int err;
while ((c = getopt(argc, argv, "c:i:b:p:r:s:")) != -1) {
switch (c) {
case 'c':
src = optarg;
break;
case 'i':
dst = optarg;
break;
case 'b':
block_size = to_int(optarg);
break;
case 'p':
prog_size = to_int(optarg);
break;
case 'r':
read_size = to_int(optarg);
break;
case 's':
fs_size = to_int(optarg);
break;
}
}
if ((src == NULL) || (dst == NULL) || (block_size <= 0) || (prog_size <= 0) ||
(read_size <= 0) || (fs_size <= 0)) {
usage();
exit(1);
}
// Mount the file system
cfg.read = lfs_read;
cfg.prog = lfs_prog;
cfg.erase = lfs_erase;
cfg.sync = lfs_sync;
cfg.block_size = block_size;
cfg.read_size = read_size;
cfg.prog_size = prog_size;
cfg.block_cycles = 256;
cfg.cache_size = 2 * read_size;
cfg.block_count = fs_size / cfg.block_size;
cfg.lookahead_size = cfg.block_count;
cfg.context = NULL;
data = calloc(1, fs_size);
if (!data) {
fprintf(stderr, "no memory for mount\r\n");
return -1;
}
err = lfs_format(&lfs, &cfg);
if (err < 0) {
fprintf(stderr, "format error: error=%d\r\n", err);
return -1;
}
err = lfs_mount(&lfs, &cfg);
if (err < 0) {
fprintf(stderr, "mount error: error=%d\r\n", err);
return -1;
}
compact(src);
FILE *img = fopen(dst, "wb+");
if (!img) {
fprintf(stderr, "can't create image file: errno=%d (%s)\r\n", errno, strerror(errno));
return -1;
}
fwrite(data, 1, fs_size, img);
fclose(img);
return 0;
}