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>
308 lines
7.8 KiB
C
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;
|
|
}
|