Reputation: 11
fs_opendir
is not supported in ext4 filesystem, but I need to access files in a ext4 filesystem directory in uboot.
Here is what I found in uboot source code:
#if CONFIG_IS_ENABLED(FS_EXT4)
{
.fstype = FS_TYPE_EXT,
.name = "ext4",
.null_dev_desc_ok = false,
.probe = ext4fs_probe,
.close = ext4fs_close,
.ls = ext4fs_ls,
.exists = ext4fs_exists,
.size = ext4fs_size,
.read = ext4_read_file,
#ifdef CONFIG_CMD_EXT4_WRITE
.write = ext4_write_file,
.ln = ext4fs_create_link,
#else
.write = fs_write_unsupported,
.ln = fs_ln_unsupported,
#endif
.uuid = ext4fs_uuid,
.opendir = fs_opendir_unsupported,
.unlink = fs_unlink_unsupported,
.mkdir = fs_mkdir_unsupported,
},
I try using ext4fs_find_file
to check if the directory exist. If the directory exists, I try to read directories and files in it by a function modified from ext4fs_iterate_find
. And here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <common.h>
#include <command.h>
#include <fs.h>
#include <blk.h>
#include <ext4fs.h>
#include <part.h>
#include <linux/ctype.h>
#include <linux/stddef.h>
#define BOOT_FLAG0 "ostree/boot.0/tcu"
#define BOOT_FLAG1 "ostree/boot.1/tcu"
#define ROLLBACK_FLAG "0"
#define HASH_SIZE 64
#define OLD_BOOTARGS "old_bootargs"
extern int ext4fs_read_file(struct ext2fs_node *node, loff_t pos,
loff_t len, char *buf, loff_t *actread);
static int ext4fs_iterate_find_ostree_hash(struct ext2fs_node *dir, char **hash) {
unsigned int fpos = 0;
int status;
loff_t actread;
struct ext2fs_node *diro = (struct ext2fs_node *) dir;
if (!diro->inode_read) {
status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode);
if (status == 0)
return 0;
}
/* Search the file. */
while (fpos < le32_to_cpu(diro->inode.size)) {
struct ext2_dirent dirent;
status = ext4fs_read_file(diro, fpos,
sizeof(struct ext2_dirent),
(char *)&dirent, &actread);
if (status < 0) {
return 1;
}
if (dirent.filetype != FILETYPE_DIRECTORY) {
printf("Invalid file in path\n");
return 1;
}
if (dirent.direntlen != HASH_SIZE) {
printf("Hash size not match: %d\n", dirent.direntlen);
return 1;
}
struct ext2fs_node *fdiro;
int type = FILETYPE_UNKNOWN;
status = ext4fs_read_file(diro,
fpos +
sizeof(struct ext2_dirent),
dirent.namelen, *hash,
&actread);
if (status < 0) {
return 1;
}
// fdiro = zalloc(sizeof(struct ext2fs_node));
// if (!fdiro) {
// return 0;
// }
// fdiro->data = diro->data;
// fdiro->ino = le32_to_cpu(dirent.inode);
*hash[dirent.namelen] = '\0';
// free(fdiro);
fpos += le16_to_cpu(dirent.direntlen);
}
return 0;
}
static int read_ostree_hash(const char *dirname, char **hash) {
struct ext2fs_node *dirnode = NULL;
int status;
if (dirname == NULL)
return 1;
status = ext4fs_find_file(dirname, &ext4fs_root->diropen, &dirnode,
FILETYPE_DIRECTORY);
if (status != 1) {
printf("** Can not find directory. **\n");
if (dirnode)
ext4fs_free_node(dirnode, &ext4fs_root->diropen);
return 1;
}
if (ext4fs_iterate_find_ostree_hash(dirnode, hash)) {
return 1;
}
ext4fs_free_node(dirnode, &ext4fs_root->diropen);
return 0;
}
static int ext4_dir_exists(const char *dirname) {
struct ext2fs_node *dirnode = NULL;
int status;
if (dirname == NULL)
return 1;
return ext4fs_find_file(dirname, &ext4fs_root->diropen, &dirnode,
FILETYPE_DIRECTORY);
}
static int update_bootargs_env_with_ostree_env(const char* ostree_env) {
char *old_env = NULL;
char new_env[1000];
old_env = env_get(OLD_BOOTARGS);
if (old_env == NULL) {
old_env = env_get("bootargs");
if (old_env == NULL) {
printf("[ERR] error bootargs read!\n");
return 1;
}
env_set(OLD_BOOTARGS, old_env);
}
sprintf(new_env, "%s %s", old_env, ostree_env);
env_set("bootargs", new_env);
return 0;
}
int ostree_boot(const char *ifname, const char *dev_part, int is_rollback) {
struct fs_dir_stream *dirs = NULL;
struct fs_dirent *dent = NULL;
char boot_dir[100];
char hash[HASH_SIZE + 1];
char cmd0[1024];
char cmd1[1024];
memset(hash, 0, sizeof(hash));
memset(boot_dir, 0, sizeof(boot_dir));
printf("[STEP]1 Find boot path\n");
if (ext4_dir_exists(BOOT_FLAG0) == 0) {
printf("[INFO] boot at %s\n", BOOT_FLAG0);
memcpy(boot_dir, BOOT_FLAG0, strlen(BOOT_FLAG0));
} else if (ext4_dir_exists(BOOT_FLAG1) == 0) {
printf("[INFO] boot at %s\n", BOOT_FLAG1);
memcpy(boot_dir, BOOT_FLAG1, strlen(BOOT_FLAG1));
} else {
printf("[ERROR] Can not ls boot dir\n");
return 1;
}
printf("[STEP]2 Get boot hash\n");
if (read_ostree_hash(boot_dir, &hash)) {
return 1;
}
char boot_str[500];
memset(boot_str, 0, sizeof(boot_str));
sprintf(boot_str, "ostree=%s/%s/%u, ostree_root=/dev/mmcblk0p4", boot_dir, hash, is_rollback ? 1 : 0);
printf("[STEP]3 Update bootargs\n");
if (update_bootargs_env_with_ostree_env(boot_str)) {
printf("[ERROR] Failed to update bootargs\n");
return 1;
}
return 0;
}
int do_ostree_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) {
if (argc != 3) {
printf("Usage: ostree_boot ifname <device>:<partition>\n");
return 1;
}
if (ostree_boot(argv[1], argv[2], 0)) {
return 1;
}
}
int do_ostree_rollback(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) {
if (argc != 3) {
printf("Usage: ostree_rollback ifname <device>:<partition>\n");
return 1;
}
if (ostree_boot(argv[1], argv[2], 1)) {
return 1;
}
}
U_BOOT_CMD(
ostree_rollback,
3,
1,
do_ostree_rollback,
"format : do_ostree_rollback <dev>:<part> <is_rollback>",
"example: do_ostree_rollback 0:1 0"
);
U_BOOT_CMD(
ostree_boot,
3,
1,
do_ostree_boot,
"format: ostree_boot <ifname> <dev>:<part>",
"example: ostree_boot mmc 0:4"
)
Once I execute the command ostree_boot
, U-boot crashes and output is here:
"Synchronous Abort" handler, esr 0x96000004
elr: 000000008205a3f0 lr : 000000008205b504 (reloc)
elr: 00000000f7b7e3f0 lr : 00000000f7b7f504
x0 : 350001400a050000 x1 : 0000000000000000
x2 : 0000000000000008 x3 : 00000000f79dff68
x4 : 00000000f79dff60 x5 : 0000000000000180
x6 : 0000000000000000 x7 : 00000000f7a07030
x8 : 0000000000000000 x9 : 0000000000000008
x10: 0000000000000044 x11: 000000000000000d
x12: 0000000000000006 x13: 000000000001869f
x14: 00000000f79e09d0 x15: 0000000000000002
x16: 00000000f7b4cc68 x17: 0000000000000000
x18: 00000000f79e3d90 x19: 0000000000000008
x20: 0000000000000001 x21: 00000000b9468040
x22: 0000000000000000 x23: 0000000000000000
x24: 000000004d8bffa7 x25: 00000000f79e000c
x26: 00000000b2740063 x27: 00000000f7bb4000
x28: 00000000f7a06290 x29: 00000000f79dfe00
Code: f94000a0 4b1a0318 b9400cb5 f90033e5 (b9401800)
Resetting CPU ...
I put the directories and files in mmc 0:4
Upvotes: 1
Views: 118